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
posted @ 2016-03-26 19:39  qingguoing  阅读(5908)  评论(0编辑  收藏  举报