首页 > 代码库 > 浅谈prototype与__proto__

浅谈prototype与__proto__

其实这两个东西指向的是同一个。

对构造函数来说,它有一个prototype的对象,用来在初始化实例时往实例的__proto__对象中添加属性或者方法,对于实例来说,它有一个__proto__对象,这个对象在被该实例被初始化时被创建且从构造函数的prototype对象里继承属性或方法。

可以把从构造函数角度的prototype及从实例角度的__proto__看成是一个东西。

验证代码如下:

console.log(test.prototype===new test().__proto__)console.log(test.prototype===new test().constructor.prototype);

结果返回都为true 注:实例的constructor指向这个实例的构造函数本身。

而__proto__对于实例本身的属性而言的逻辑为,当javascript去寻找一个实例的某个属性时,假设为a属性,如果这个实例本身有a这个属性,就会输出这个属性,如果没有,那么就会去这个实例的__proto__中去找a这个属性。

P.S 构造函数本身也可看作是一个实例。

验证代码如下:

function test(){    this.a = b;};test.prototype.a = w;var c = new test();console.log(c.a)//输出为‘b‘

解读:构造函数给实例本身添加属性a值为‘b‘,再通过构造函数的prototype为实例的__proto__添加属性a值为‘w‘,这两个同名属性都是存在的,这时输出实例c的a属性,结果为‘b‘,所以当实例本身拥有这个属性的时候,构造函数的prototype为实例的__proto__添加这个同名属性都会被无视,javascript一旦在实例本身找到这个属性就会输出而不会理会__proto__中的同名属性。

 

那假设在构造函数中不给实例添加这个同名属性呢。

function test(){    };test.prototype.a = w;var c = new test();console.log(c.a)//输出为‘w‘

解读:这回我们没用通过构造函数给实例本身添加属性a,javascript在寻找实例的a属性时,在其本身没有找到,于是去它的__proto__寻找,构造函数的prototype为实例的__proto__添加了此属性,所以找到了,输出‘w‘。

 

验证2:从实例的__proto__属性可以改变构造函数的prototype。

验证代码:

function test(){    };test.prototype.b = w;var c = new test();var d = new test();c.__proto__.b = s;console.log(c.b)console.log(d.b)//输出都为‘s‘

 

解读:构造函数prototype添加实例__proto__的属性b值为‘w‘,通过实例c的__proto__改变属性b的值为‘s‘,结果都输出为‘s‘,这就说明了,通过实例的可以改变prototype的赋值,其实若把__proto__与prototype看成是一个东西的话就好解释了,无论是通过函数的prototype还是实例的__proto__改变其中的属性及值,包括新生成实例,每一次改动后的输出值都以每次的改动为准。最后一段代码来说明这个问题。

function test(){    };test.prototype.b = w;//实例c跟dvar c = new test();var d = new test();//实例后未做改变输出console.log(c.b);    //输出‘w‘console.log(d.b);    //输出‘w‘//以实例c的__proto__修改属性b为‘s‘c.__proto__.b = s;console.log(c.b)    //输出‘s‘console.log(d.b)    //输出‘s‘//以实例d的__proto__修改属性b为‘f‘d.__proto__.b = f;console.log(c.b)    //输出‘f‘console.log(d.b)    //输出‘f‘//新实例一个evar e = new test();//很明显还是上次修改的‘f‘console.log(e.b)    //输出‘f‘//通过构造函数的prototype再修改为‘g‘test.prototype.b = g;console.log(c.b)    //输出‘g‘console.log(d.b)    //输出‘g‘console.log(e.b)    //输出‘g‘//通过实例c的constructor指向到它的构造函数再通过prototype修改为‘h‘c.constructor.prototype.b = h;console.log(c.b)    //输出‘h‘console.log(d.b)    //输出‘h‘console.log(e.b)    //输出‘h‘

 

浅谈prototype与__proto__