搜尋

首頁  >  問答  >  主體

javascript - 关于js原型中引用类型的问题?

person1作为一个实例,为什么可以改变原型里面的内容?这中间发生了什么?能不能从内存角度解释一下。。

PHP中文网PHP中文网2823 天前165

全部回覆(2)我來回復

  • 巴扎黑

    巴扎黑2017-04-10 17:14:32

    默认情况下,实例的原型就是它的构造函数的prototype所引用的对象。也就是说

    person1.__proto__ === person2.__proto__ === Person.prototype

    这3者是同一个对象。

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-10 17:14:32

    公有属性和私有属性

    Person作为一个类,会有自己的一些公有属性和私有属性,你可以将prototype理解成这个类的公有属性,既然是公有的,那就是别人也能使用并且改变的。person1和person2都具有Person这个类的公有方法和属性,当person1改变了公有属性,另一个也实例person2的属性值也改变了。从内存的角度来讲,公有属性在内存里的就只有一个地址,前者(person1)操作完了,后者(person2)去读取的时候自然就是刚刚改完的。
    为了避免这种情况,就应该把不想被共享的属性私有化,如下代码:

    function Person(friends) {
        if ( friends )
            this.friends = friends;
    }
    
    Person.prototype = {
        constructor: Person,
    
        name: 'Nicholas',
    
        age: '29',
    
        job: 'Software Engineer',
    
        friends: ['Shelby', 'Counrt'],
    
        sayName: function() {
            alert(this.name);
        }
    };
    
    var person1 = new Person(['Van']);
    var person2 = new Person();
    
    person1.friends.push("Van");
    
    console.log(person1.friends);//['Van', 'Van']
    console.log(person2.friends);//['Shelby', 'Counrt']

    补充一句,属性的查找是基于原型链的,person1有自己的私有属性friends也有公有属性friends,取值的时候先查找有没有私有属性,再去查找公有属性,如果公有属性也没有,就继续往上找(Object构造函数),直到顶端。

    基础类型的值的操作和引用类型的值的操作

    书上的Demo中friends是数组,也就是引用类型的对象,push是这个数组具有的一个方法,所以调用push方法的时候并不会改变这个对象的内存地址。如果你是直接赋值,实际上是定义了私有属性:

    function Person() {
        
    }
    
    Person.prototype = {
        constructor: Person,
    
        name: 'Nicholas',
    
        age: '29',
    
        job: 'Software Engineer',
    
        friends: ['Shelby', 'Counrt'],
    
        sayName: function() {
            alert(this.name);
        }
    };
    
    var person1 = new Person(['Van']);
    var person2 = new Person();
    
    person1.friends = "Van";
    
    console.log(person1);// Person {friends: 'Van'}
    console.log(person2);// Person {}

    结论

    书上的demo,因为是person1.friends.push,所以friends一定是具有push方法的,而公有属性'friends'恰恰具有这个方法,也即是先执行了查找操作。
    对于上面的第二个demo,由于是赋值操作,改变了内存空间,Javascript认为这是声明私有变量操作,原有的公有属性不会改变

    回覆
    0
  • 取消回覆