AngularJS:复制vs扩展

时间:2016-04-24 19:28:35

标签: javascript angularjs deep-copy shallow-copy

说明:

我们遇到了一些需要将一个对象复制到另一个对象的情况。在这种情况下,我们可能有两个解决方案:angular.copy()angular.extend()

我面临的挑战:

我们知道angular.copy(source, destination)创建源对象的深层副本并将其分配给目标。通过编写深层副本,我们的意思是所引用对象的新副本及其工作正常。

深层复制代码:

var mySource = {'name' : 'Rohit', 'age' : '24'}
var myDest = {}
angular.copy(mySource,myDest);
mySource.name = "Jindal";
console.log(mySource); // Object {name: "Jindal", age: "24"}
console.log(myDest); // Object {name: "Rohit", age: "24"}
console.log(mySource.obj === myDest.obj); // false

在这里,我修改了源对象mySource.name = "Jindal",但它没有像预期的那样影响目标对象myDest。 如果我们检查mySource.obj === myDest.obj,这将给出错误,因为它们都指向不同的对象。

现在,我遇到angular.extend(destination, source)的问题,因为它创建了shallow copy手段,因此源和目标都指向相同的地址。 So, if i will modify source object then it will also reflect in destination object. But it's not happening.

浅拷贝代码:

var mySource = {'name' : 'Rohit', 'age' : '24'}
var myDest = {}
angular.extend(myDest,mySource);
mySource.name = "Jindal";
console.log(mySource); // Object {name: "Jindal", age: "24"}
console.log(myDest); // Object {name: "Rohit", age: "24"}
console.log(mySource.obj === myDest.obj); // True

jsfiddle:https://jsfiddle.net/U3pVM/24322/

由于我是新手,需要帮助才能理解angular.copy()&的正确流程。 angular.extend()。

任何直接的帮助都会非常值得注意。谢谢

4 个答案:

答案 0 :(得分:9)

我更新了the code。现在angular.extends按预期工作。请记住,如果传递angular.extends空对象作为第一个参数(目标)然后传递源,则angular将保留两个对象并仅复制属性,就像angular.copy一样。

// angular.copy()

var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = angular.copy(mySource);

mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {name: "sakshi", age: "24", obj: Object}
console.log(mySource.obj === myDest.obj); // false

// angular.extend()

var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = angular.extend(mySource);
mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {name: "Rohit", age: "24", obj: Object}
console.log(mySource.obj === myDest.obj); // True

答案 1 :(得分:4)

agular.copy克隆(深层复制)对象并使用相同的值创建新对象,而angular.extend执行浅复制,以便属性在内存中引用相同的值。给出了一个非常好的解释here,它可以很好地区分.copy().extend().merge()方法

答案 2 :(得分:2)

原语是按值而非参考复制的,但首先要尝试理解copy vs extend

复制

迭代一个对象的每个属性,如果它是一个基元只是复制它,如果它是一个对象创建一个新对象并执行一个递归复制

实现可能如下所示,请注意,显然还有一些其他情况,但我保持简单

function copy(dest, source) {
  for (var property in source) {
    if (typeof source[property] === 'object') {
      var clone = {}
      copy(clone, source[property])
      dest[property] = clone
    } else {
      // a primitive
      dest[property] = source[property]
    }
  }
}

<强>延伸

迭代一个对象的每个属性,如果它是一个基元只是复制它,如果它是一个对象创建一个对象的引用而不是创建一个与原始对象具有相同引用的新对象

function extend(dest, source) {
  for (var property in source) {
    dest[property] = source[property]
  }
}

也许你期望当你做浅层复制时,原语也会被浅层复制,但是如上所述,它们总是被克隆,为了解决你的问题,你应该改变引用对象的属性(用浅的方法实现)拷贝)

var mySource = {person: {'name' : 'Rohit', 'age' : '24'}}
var myDest = {}
angular.extend(myDest,mySource);
mySource.person.name = "Jindal";
console.log(mySource); // Object {person: {name: "Jindal", age: "24"}}
console.log(myDest);  // Object {person: {name: "Jindal", age: "24"}}
console.log(mySource.obj === myDest.obj); // True

答案 3 :(得分:2)

对于对象的副本,以下事项是完美的。

  • 对象指向相同的内存位置

    • 正常副本 - 是
    • 角度副本 - 否
    • 角度延伸 - 否
    • 角度合并 - 否
  • 内部对象指向相同的内存位置

    • 正常副本 - 是
    • 角度副本 - 否
    • 角度延伸 - 否
    • 角度合并 - 否
  • 复制是保留当前子对象还是删除该对象

    • 正常复制 - 覆盖
    • 角度副本 - 覆盖
    • 角度延伸 - 保持
    • 角度合并 - 保持

以下是

plunker副本
// '=' assignment copy
console.info('assignment copy');
var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = {oldObj:'old'} //old properties will be override
myDest = mySource;
mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {name: "sakshi", age: "24", obj: Object}
console.log(mySource === myDest); // true         //points to same object
console.log(mySource.obj === myDest.obj); // true //points to same object


// angular.copy()
console.info('angular copy');
var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = {oldObj:'old'} //old properties will be override
angular.copy(mySource,myDest);
mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {name: "sakshi", age: "24", obj: Object}
console.log(mySource === myDest); // false //points to different object
console.log(mySource.obj === myDest.obj); // false //points to different object

// angular.extend()
console.info('angular extend');
var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = {oldObj:'old'}
angular.extend(myDest,mySource);
mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {oldObj:'old',name: "sakshi", age: "24", obj: Object}
mySource.obj.key = '123';
console.log(myDest.obj.key);
console.log(mySource === myDest); // false //points to different object
console.log(mySource.obj === myDest.obj); // True //points to same object

// angular.extend()
console.info('angular merge');
var mySource = {'name' : 'sakshi', 'age' : '24', 'obj' :{'key':'value'}}
var myDest = {oldObj:'old'}
angular.merge(myDest,mySource);
mySource.name = "Rohit";
console.log(mySource); // Object {name: "Rohit", age: "24", obj: Object}
console.log(myDest); // Object {oldObj:'old',name: "sakshi", age: "24", obj: Object}
console.log(mySource === myDest); // false //points to different object
console.log(mySource.obj === myDest.obj); // false //points to different object