现在遇到一个引用传递的问题,用代码说明吧
var Lan = function(){};
var Attr1 = function(){
this.name = 'attr1';
}
var Attr2 = function(){
this.name = 'attr2';
}
Lan.prototype.attr = new Attr1();
var lan = new Lan();
var obj = lan.attr;//这一步不应该是传递的Lan原型链上的引用吗
console.log(obj1);//输出Attr1 {name: "attr1"}
Lan.prototype.attr = new Attr2();//Lan原型链的属性改变,指向Attr2的对象,那obj不也应该指向Attr2的对象?
console.log(obj);//输出Attr1 {name: "attr1"},但结果却不是这样
PHP中文网2017-04-10 15:09:08
var Lan = function(){};
var Attr1 = function(){
this.name = 'attr1';
}
var Attr2 = function(){
this.name = 'attr2';
}
Lan.prototype.attr = new Attr1();
var lan = new Lan();
var obj = lan.attr;//这一步不应该是传递的Lan原型链上的引用吗 [1]
console.log(obj1);//输出Attr1 {name: "attr1"}
Lan.prototype.attr = new Attr2();//Lan原型链的属性改变,指向Attr2的对象,那obj不也应该指向Attr2的对象? [2]
console.log(obj);//输出Attr1 {name: "attr1"},但结果却不是这样 , [3]
[1]obj 和 Lan.prototype.attr 同时指向 new Attr1() 创建的对象
[2]Lan.prototype.attr重指向 new Attr2()创建的对象,而obj 指向的对象没有变(new Attr1() 创建的对象没有消失,内存中依旧存在)
[3]obj 指向的对象指向的还是原来的对象
天蓬老师2017-04-10 15:09:08
var foo = {};
foo.a = 'aa';
var bar = foo.a
console.log(bar); //aa
foo.a = 'bb';
console.log(bar); //aa
简化下,大概是这样吧
高洛峰2017-04-10 15:09:08
你下面打印错了,你改变原型之后,打印的还是之前new的那个lan,所以当然还是一样的结果,上代码,我手机端,无法编辑代码格式,你凑合看,主要我下面new了一个新的lan1,然后打印lan1,也就是更改之后的,
var Lan = function(){};
var Attr1 = function(){
this.name = 'attr1';
}
var Attr2 = function(){
this.name = 'attr2';
}
Lan.prototype.attr = new Attr1();
var lan = new Lan();
var obj = lan.attr;
console.log(obj.name)
Lan.prototype.attr = new
Attr2();
var lan1=new Lan;
var obj1=lan.attr;
console.log(obj1.name);//输出Attr2
阿神2017-04-10 15:09:08
我们可以分解下看看:
...
// 把Attr1的一个instance赋值给Lan.prototype.attr,即Lan.prototype.attr指向了这个Attr1的instance
// 记作attr1Instance
Lan.prototype.attr = new Attr1();
var lan = new Lan();
// 这里obj指向了attr1Instance
var obj = lan.attr;
// 让Lan.prototype.attr指向Attr2的一个instance,
// 这里并没有改变obj的指向
Lan.prototype.attr = new Attr2();
最后, 如果console.log(lan.attr), 应该得到[Object] {name: 'attr2'}
ringa_lee2017-04-10 15:09:08
最后如果你console.log(lan.attr)
,那结果就是Attr2 {name: "attr2"}
,因为你obj
还是指的那个对象。
相当于b = 1;a = b;b = 2
;这时,a的value为1
,而不是2
。
天蓬老师2017-04-10 15:09:08
一、obj 和 lan 原型对象 attr 属性同时指向 object { name: 'attr1' }
二、obj 依旧指向 object { name: 'attr1' }; lan 原型上的 attr 指向 object { name: 'attr2' }
大家讲道理2017-04-10 15:09:08
Javascript中的赋值策略 不仅仅是 按值传递、按引用传递 这么简单;
看一个在 stackoverflow 上的回答:Javascript by reference vs. by value:
- Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
- Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
- However, changing a property of an object referenced by a variable does change the underlying object.
再来看段代码:
javascript
function changeStuff(num, obj1, obj2){ num = num * 10; obj1.item = "changed";//只是修改obj1的一个属性 obj2 = {item: "changed"};//修改了obj2这个对象 } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num);//10 console.log(obj1.item);// "changed" console.log(obj2.item);// "unchanged"
以上为Javascript中赋值会遇到的一些情况,有点偏题了;
这些都只是表现,具体的原理可以看下这篇文章:深入理解JavaScript系列(19):求值策略(Evaluation strategy);
回头来看你遇到的问题:
javascript
var Lan = function(){}; var Attr1 = function(){ this.name = 'attr1'; };// 假设 内存地址为 0xFE var Attr2 = function(){ this.name = 'attr2'; };// 假设 内存地址为 0xFF Lan.prototype.attr = new Attr1(); // Lan.prototype.attr 指向 内存地址 0xFE var lan = new Lan(); var obj = lan.attr;//这里 obj 指向 内存地址 0xFE console.log(obj);//输出Attr1 {name: "attr1"} => 0xFE Lan.prototype.attr = new Attr2();// Lan.prototype.attr 指向 内存地址 0xFF console.log(obj);//输出Attr1 {name: "attr1"} => 0xFE console.log(lan.attr);//输出Attr2 {name: "attr2"} => 0xFF
你遇到的问题 关键在 var obj = lan.attr;
这个赋值引起的;
可以这么理解 obj 在赋值的时候 获得了 lan.attr 的内存地址 0xFE;
后面再修改 Lan.prototype.attr的内存地址为 0xFF,并不会影响到 obj;
所以 console.log(obj);
和console.log(lan.attr);
的结果并不一样;
注: 内存地址只是我自己的理解,并不一定准确;