1 <script> 2 var fun1 = function(){ 3 this.name = 'peter'; 4 return { 5 name: 'jack' 6 }; 7 } 8 var p1 = new fun1(); 9 console.log(p1.name)//jack 10 11 var fun2 = function(){ 12 this.name = 'peter'; 13 return 'jack'; 14 } 15 var p2 = new fun2(); 16 console.log(p2.name)//peter 17 </script>
1 <script> 2 var fun = function(){} 3 fun.prototype = { 4 info : { 5 name : 'peter', 6 age : 25 7 } 8 } 9 10 var a = new fun(); 11 var b = new fun(); 12 a.info.name = 'jack'; 13 b.info.name = 'tom'; 14 console.log(a.info.name)//tom 15 console.log(b.info.name)//tom 16 </script>
1 var a = {"x": 1}; 2 var b = a; 3 a.x = 2; 4 b.x; //2 5 6 a = {"x":3}; 7 b.x;//2 8 a.x = 4; 9 b.x;//2
首先定义一个对象a,有一个属性x,值为1。接着让b = a,这一步的结果就是a和b指向了同一个对象。
在内存中,对象的存储和基本数据类型不同。基本数据类型直接保存在栈里,a = 1,b = 1,在栈里会保存两份1,分别赋值给a和b。修改a或b,对另一个变量不会有什么影响。
对象则不然,变量a和b如果被赋值对象,a和b实际上保存的只是对象的地址,而且a和b还是被存储在栈里,同时a和b的地址是相同的。但对象是在堆里保存,且只保存一份,对象的地址就是a和b的值,a和b都指向同一个对象。这与C里面的指针类似,修改指向同一个对象的任何一个变量,与之引用同一对象变量很快就会发生同样的变化。如下图:
所以现在的情况就是,a和b都指向了堆中的一个对象,这个对象的属性x值是1。那么a.x = 1,b.x自然也等于1。
1 |
a.x = 2 |
接下来发生一件事情,a修改了对象的x属性为2,这个变化反映到了堆中:
看,a和b还是指向了同一个对象,只不过对象中的x属性值变成了2。这一变化b很快就发现了,所以你再去访问b.x,实际上就是访问堆中的对象的x属性,也就是2。
1 |
a = {"x":3}; |
再后来,为a赋值了一个新的对象,虽然它也有一个属性x,但它确实是一个新对象!那么内存堆中发生了什么呢?首先,堆中原有的对象(x = 2的那个)还在那里。因为新建了一个对象(x = 3的),堆中就会出现一个新的对象,与原来的对象毫无关系。同时,b并没有变化,它还指向原有的对象(x = 2),但a指向原来的对象的地址却发生了变化,它指向了x = 3的这个新对象。
a的地址变了,同时a和原来的对象也没有指向关系了,它指向了新的对象,这个新对象的x = 3。而b对象没有任何变化,它还坚守着自己的对象,对象的x属性是2。
1 |
a.x = 4; |