AngularJS:复制与扩展
AngularJS : copy vs extend
解释:
我们遇到过需要将一个对象复制到另一个对象的情况。在那种情况下,我们可能有两种解决方案:angular.copy() or 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
,这将给出 false,因为两者都指向不同的对象。
现在,我遇到了 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() 的正确流程。
我们将不胜感激任何直接的帮助。谢谢
我更新了 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
agular.copy
克隆(深拷贝)一个对象并使用相同的值创建一个新对象,而 angular.extend
进行浅拷贝以便属性引用内存中的相同值。 here 给出了一个非常好的解释,它很好地区分了 .copy()
、.extend()
和 .merge()
方法
基元是按值而不是按引用复制的,但首先尝试理解 copy
与 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
对于对象的副本,以下内容很重要。
对象是否指向相同的内存位置
正常复制 - 是
Angular 复制 - 否
Angular 延长 - 否
Angular 合并 - 否
内部对象是否指向相同的内存位置
正常复制 - 是
Angular 复制 - 否
Angular 延长 - 否
Angular 合并 - 否
复制是保留当前子对象还是删除该对象
普通复制 - 覆盖
Angular 复制 - 覆盖
Angular 延长 - 保持
Angular合并-保留
这是 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.copy() or 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
,这将给出 false,因为两者都指向不同的对象。
现在,我遇到了 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() 的正确流程。
我们将不胜感激任何直接的帮助。谢谢
我更新了 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
agular.copy
克隆(深拷贝)一个对象并使用相同的值创建一个新对象,而 angular.extend
进行浅拷贝以便属性引用内存中的相同值。 here 给出了一个非常好的解释,它很好地区分了 .copy()
、.extend()
和 .merge()
方法
基元是按值而不是按引用复制的,但首先尝试理解 copy
与 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
对于对象的副本,以下内容很重要。
对象是否指向相同的内存位置
正常复制 - 是
Angular 复制 - 否
Angular 延长 - 否
Angular 合并 - 否
内部对象是否指向相同的内存位置
正常复制 - 是
Angular 复制 - 否
Angular 延长 - 否
Angular 合并 - 否
复制是保留当前子对象还是删除该对象
普通复制 - 覆盖
Angular 复制 - 覆盖
Angular 延长 - 保持
Angular合并-保留
这是 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