Javascript对象赋值操作
首先,我们还是举个例子来说明对象赋值操作的问题吧:
ps: 本文默认约定log = console.log
function A(){}
A.prototype.x = 10;
var a1 = new A();
A.prototype = {
x: 20,
y: 20
};
var a2 = new A();
log([a1.x, a1.y, a2.x, a2.y]); // [10, undefined, 20, 20]
js中对象赋值操作我们可以通过c语言中得指针概念来解释。
对象的浅拷贝
直接通过赋值操作符“=”将变量a中的对象赋值给变量b,此时我们更改a、b其中一个,另一个也会随之更改。
var a = [1, 1],
b = a;
b[0] = 2;
log(a[0]); // 2
因为我们在将a的对象赋值给b时,js引擎内部的操作只是简单的将a所指的对象的地址赋值给b,此时a与b指向内存中同一个对象,所以才会出现这种情况。这种赋值方式称为对象的浅拷贝。
我们可以从另一个方面论证我们的观点:
log(a === b); // true,毫无疑问
var c = [2, 1];
log(a === c); // false
出现这种情况的原因就是变量c指向的是另一个和变量a指向的对象的值相同的对象,仅仅只是两个指向的对象的值相同,但两个对象在内存的地址是不一样的,所以是false。
另外,我们知道js数组中有一些方法可以实现数组的完全复制,即两个变量分别指向两个对象:
b = a.concat([]),
c = a.slice(0),
d = a.splice(0, a.length);
log(b === a); // false
但是我们要针对对象进行复制的话,只能手动进行模拟,即所谓的对象深拷贝。
对象的深拷贝
顾名思义,就是利用“=”对于基本类型的操作不存在上述问题,通过for-in深度遍历对象的属性,然后将其赋值给另一个新的对象。
function cloneObj(obj) {
var tempObj = {};
if (obj instanceof Array) {
tempObj = [];
}
for (var prop in obj) {
if (typeof prop === 'Object') {
cloneObj(prop);
}
tempObj[prop] = obj[prop];
}
return tempObj;
}
var myCountry = {
name: 'China',
birth: 1949
},
country = cloneObj(myCountry);
log(country === myCountry); // false
结束语
最后,我们回到第一个例子,会发现,引擎内部对于new对象的原型链也是通过简单的赋值操作的方式,即对象的浅拷贝。而ES5新增的Object.create()
也是浅拷贝的一种封装:
var myCountry = {
name: 'China',
birth: 1949
},
country = Object.create(myCountry);
console.log(country.__proto__ === myCountry); // true
如果你觉得本文对你有帮助,请点击右下角的推荐让更多人知道^_^
欢迎光临个人网站 qingguoing.com