【问题标题】:AngularJS : copy vs extendAngularJS:复制与扩展
【发布时间】:2016-08-18 02:15:24
【问题描述】:

说明:

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

我面临的挑战:

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

深拷贝代码:

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

在这里,我修改了源对象mySource.name = "Alpha",但它并没有像预期的那样影响目标对象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' : 'Beta', 'age' : '24'}
var myDest = {}
angular.extend(myDest,mySource);
mySource.name = "Alpha";
console.log(mySource); // Object {name: "Alpha", age: "24"}
console.log(myDest); // Object {name: "Beta", age: "24"}
console.log(mySource.obj === myDest.obj); // True

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

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

任何直接的帮助都将是非常可观的。谢谢

【问题讨论】:

    标签: javascript angularjs deep-copy shallow-copy


    【解决方案1】:

    对于对象的副本,以下内容很重要。

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

    • 普通副本 - 是

    • 角复制 - 否

    • 角度扩展 - 否

    • 角度合并 - 否

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

    • 普通副本 - 是

    • 角复制 - 否

    • 角度扩展 - 否

    • 角度合并 - 否

    • 复制是保留当前子对象还是删除该对象

    • 普通副本 - 覆盖

    • 角度复制 - 覆盖

    • 角度扩展 - 保持

    • 角度合并 - 保持

    这是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 = "Beta";
    console.log(mySource); // Object {name: "Beta", 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 = "Beta";
    console.log(mySource); // Object {name: "Beta", 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 = "Beta";
    console.log(mySource); // Object {name: "Beta", 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 = "Beta";
    console.log(mySource); // Object {name: "Beta", 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
    

    【讨论】:

    • 您的代码显示了一件事(angular.extend 对内部对象使用相同的引用),而您的摘要说明了另一件事。
    • 是的。我认为 angular.extend 在“内部对象是否指向相同的内存位置”列表中应该是“是”。
    【解决方案2】:

    我更新了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 = "Beta";
    console.log(mySource); // Object {name: "Beta", 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 = "Beta";
    console.log(mySource); // Object {name: "Beta", age: "24", obj: Object}
    console.log(myDest); // Object {name: "Beta", age: "24", obj: Object}
    console.log(mySource.obj === myDest.obj); // True
    

    【讨论】:

      【解决方案3】:

      原语是按值而不是按引用复制的,但首先要了解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' : 'Beta', 'age' : '24'}}
      var myDest = {}
      angular.extend(myDest,mySource);
      mySource.person.name = "Alpha";
      console.log(mySource); // Object {person: {name: "Alpha", age: "24"}}
      console.log(myDest);  // Object {person: {name: "Alpha", age: "24"}}
      console.log(mySource.obj === myDest.obj); // True
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2016-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-30
          • 2013-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多