其实这两个东西指向的是同一个。
对构造函数来说,它有一个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跟d var 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‘ //新实例一个e var 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‘