search

Home  >  Q&A  >  body text

javascript - JS中的引用传递问题

现在遇到一个引用传递的问题,用代码说明吧

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中文网PHP中文网2901 days ago394

reply all(7)I'll reply

  • PHP中文网

    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 指向的对象指向的还是原来的对象

    reply
    0
  • 天蓬老师

    天蓬老师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
    

    简化下,大概是这样吧

    reply
    0
  • 高洛峰

    高洛峰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

    reply
    0
  • 阿神

    阿神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'}

    reply
    0
  • ringa_lee

    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

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:09:08

    一、obj 和 lan 原型对象 attr 属性同时指向 object { name: 'attr1' }

    二、obj 依旧指向 object { name: 'attr1' }; lan 原型上的 attr 指向 object { name: 'attr2' }

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-10 15:09:08

    Javascript中的赋值策略 不仅仅是 按值传递、按引用传递 这么简单;
    看一个在 stackoverflow 上的回答:Javascript by reference vs. by value:

    1. Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
    2. Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
    3. However, changing a property of an object referenced by a variable does change the underlying object.

    再来看段代码:

    javascriptfunction 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);

    回头来看你遇到的问题:

    javascriptvar 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);的结果并不一样;

    注: 内存地址只是我自己的理解,并不一定准确;

    reply
    0
  • Cancelreply