影响新对象的一方是更改原始对象

时间:2016-07-27 04:28:56

标签: javascript inheritance scope

预期结果

我已经编写了一个函数来获取一个简单的对象文字,并重新格式化它,如下例所示:

var original = { a: 1, b: true, c: "a string" }

// run through function ...

var result = { 
  a: { type: "int", val: 1 }, 
  b: { type: "bit", val: 1 }, 
  c: { type: "varchar(250)", val: "a string" }
}

当前解决方案

该函数有效,使用for ... in循环迭代原始对象&基于原始数据构建新对象。

function change (data) {

  function loop (d) {

    var orig = d;
    var end = d;

    for (var key in orig) {

      var property = {
        type: "test",
        val: orig[key]
      };

      end[key] = property;
    }

    return end;
  }

  // create object using loop & return
  var p = loop(data);
  return p;

}

实际结果

但是,此功能还会更改传入的原始对象。我似乎无法弄清楚原因。

var original = { a: 1, b: true, c: "a string" }

// run through function ...
var result = change(original);  

console.log(result);    // =>  { 
                        //        a: { type: "int", val: 1 }, 
                        //        b: { type: "bit", val: 1 }, 
                        //        c: { type: "varchar(250)", val: "a string" }
                        //      }

console.log(original);  // =>  { 
                        //        a: { type: "int", val: 1 }, 
                        //        b: { type: "bit", val: 1 }, 
                        //        c: { type: "varchar(250)", val: "a string" }
                        //      }
                        // instead of expected: 
                        //      { a:1, b:true, c:"a string" }

我猜这与我在javascript&中完全不了解范围有关。可能关于原型继承(我肯定需要了解更多),但在这一点上,我不知道从哪里开始真正理解这里发生了什么。当我将它与我在JavaScript中对副作用的简单理解进行比较时,我感到更加困惑:

var a = 1;
var b = a;
console.log(a) // => 1
console.log(b) // => 1

b = 2
console.log(a) // => 1
console.log(b) // => 2

该功能按原样运行,并且在我的程序的其余部分正在执行我需要的功能,但是这个问题真的很困扰我,因为我不明白这里发生了什么。

1 个答案:

答案 0 :(得分:1)

在Javascript中,当一个对象作为参数传递时,如果您决定在将作为对原始对象的引用的函数中对其进行变异,并且也会使其变异。

如果您只是像只读一样处理它,它就像一个常规参数(通过值传递)

对于平坦的对象(不包含嵌套对象),您可以使用Object.assign(Es6功能和可用的polyfill)

let obj1 = { a: 1};
let obj2 = Object.assign({}, obj1);

对于更复杂的对象,我建议您使用一些库方法,如lodash' s _.cloneDeep

// you have to include lodash.js in your page
let obj1 = { a: 1};
let obj2 = _.cloneDeep(obj1);

或jQuery' $.extend

// you have to include jquery.js in your page
let obj1 = { a: 1};
let obj2 = $.extend(true, {}, obj1);