Explanation :
we come across some situation in which we need to copy one object to another object. In that case, we probably have two solutions: ang
agular.copy
clones (deep copy) an object and creates a new object using the same values, while angular.extend
does a shallow copy so that the attributes refer to same values in memory. A very nice explanation is given here which differentiates very well between .copy()
, .extend()
and .merge()
methods
I updated the code . Now angular.extends works as you expected. Remember that if you pass angular.extends an empty object as first parameter (destination) and then the source, angular is going to preserve both objects and copy only the properties, just like angular.copy does.
// 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
For the copy of the object the following things metters.
Object points to same memory location or not
Inner object points to the same memory location or not
Does copy keep the current child objects or remove that objects
Here is the plunker copy for that
// '=' 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
Primitives are copied by value instead of by reference but first try to understand copy
vs extend
copy
Iterates each property of an object, if it's a primitive just copy it, if it's an object create a new object and perform a recursive copy
The implementation may looks as follows, note that obviously there are some additional cases but I'm keeping it simple
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]
}
}
}
extend
Iterates each property of an object, if it's a primitive just copy it, if it's an object create a reference to the object instead of creating a new object which has the same references as the original object
function extend(dest, source) {
for (var property in source) {
dest[property] = source[property]
}
}
Perhaps you're expecting that when you do a shallow copy primitives will also be shallow copied however as you see above they're always cloned, to solve your problem you should instead change properties of a referenced object (achieved with a shallow copy)
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