简体   繁体   English

递归替换所有对象值

[英]Replace all object values recursively

I am using angular 4 for one of my projects and i am in a situation where i have to replace all the { data } with {{ data }}. 我使用的角度4我的项目之一,我在一个情况下,我有全部更换为{ 数据 } {{ 数据 }}。 ie if i have an object like this 即如果我有这样的对象

{
    key: {
             key1: {
                       key2: "This is data {someData}",
                       key3: "This is data2 {someData2}"
                   }
         },
    key2: "This is data3 {someData3}"
}

the result should be 结果应该是

{
    key: {
             key1: {
                       key2: "This is data {{someData}}",
                       key3: "This is data2 {{someData2}}"
                   }
         },
    key2: "This is data3 {{someData3}}"
}

I am not so comfortable with recursion as on how it works . 我对递归和它的工作方式不太满意。 So i am not able to show anything that i have tried. 所以我无法展示我尝试过的任何东西。 Please help. 请帮忙。 Any help would be appreciated. 任何帮助,将不胜感激。

Hopefully you can try something like this. 希望你能尝试这样的东西。

 var orgObj = { key: { key1: { key2: "This is data {someData}", key3: "This is data2 {someData2}" } }, key2: "This is data3 {someData3}" } function changeValue(obj) { if (typeof obj === 'object') { // iterating over the object using for..in for (var keys in obj) { //checking if the current value is an object itself if (typeof obj[keys] === 'object') { // if so then again calling the same function changeValue(obj[keys]) } else { // else getting the value and replacing single { with {{ and so on let keyValue = obj[keys].replace('{', '{{').replace('}', '}}'); obj[keys] = keyValue; } } } return obj; } console.log(changeValue(orgObj)) 

Answer by @brk is good but it is mutates the input object. @brk的回答很好,但它会改变输入对象。 If someone is working with a library like React where it is important to not mutate props, then we will have to do some additional things. 如果某人正在使用像React这样的库,那么重要的是不要改变道具,那么我们将不得不做一些额外的事情。 We can either create new reference for all the objects that we find during recursive traversal. 我们可以为在递归遍历期间找到的所有对象创建新引用。 For this, we have to take care of null values since typeof null is also object 为此,我们必须处理null值,因为typeof null也是object

//typeof null is also object. But we cannot destructure it. So check that object is not null
const isValidObject = (obj) => typeof obj === 'object' && obj !== null

function changeValue(objFromProp) {
    let obj = objFromProp;

    if (isValidObject(objFromProp)) {
        //desctructure the object to create new reference
        obj = { ...objFromProp }
        // iterating over the object using for..in
        for (var keys in obj) {
            //checking if the current value is an object itself
            if (isValidObject(obj[keys])) {
                // if so then again calling the same function
                obj[keys] = changeValue(obj[keys])
            } else {
                // else getting the value and replacing single { with {{ and so on
                let keyValue = obj[keys].replace('{', '{{').replace('}', '}}');
                obj[keys] = keyValue;
            }
        }
    }
    return obj;
}

Or if we are replacing values conditionally and if we want to preserve object's reference if none of the values in an object is changed, then we can use another library like immer. 或者,如果我们有条件地替换值,并且如果我们想要保留对象的引用,如果对象中没有任何值被更改,那么我们可以使用像immer这样的另一个库。 Immer will change reference of only those objects whose at-least one field is changed. Immer将仅更改至少一个字段被更改的对象的引用。 This will be a useful optimization. 这将是一个有用的优化。 For this method, we should use version of changeValue provided by @brk . 对于这种方法,我们应该使用changeValue提供的changeValue版本。 Immer will identify mutations and change necessary references. Immer将识别突变并改变必要的参考。

import { produce } from 'immer';
const nextState = produce(objFromProp, draftState => {
    changeValue(draftState)
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM