js 为prototype的赋值在new实例之后的问题

(最近准备考研,写得实在不勤快了= =

JavaScript高级程序设计(第3版)第156页讲了原型的动态性。
即实例与原型之间的松散连接关系使得原型的属性改动可以反映在实例上。
所谓松散连接关系,即实例与原型的连接是一个指针。当搜索实例的属性时,会先搜索实例本身属性,如果没有,则在搜索原型的属性。

后面则讲了一种特殊情况,即在new实例之后,再进行prototype的赋值(重写),会破坏这种动态性。
代码如下:

function Person(){}

var man = new Person();

Person.prototype={
    name: "Tom",
    age: 20,
    saySomething: function(){
        alert("What's up?");
    }
};
console.log(man.name);

结果截图:
这里写图片描述

可以看到man.name为undefined。
这不难理解,创建一个函数都会有一个默认的prototype属性,而new新实例man之后,man的[[prototype]]指向了默认的prototype。
而在使用了对象字面量重新赋值给prototype之后,prototype的指向地址换成了新的object的地址。而man指向的还是原有的默认的prototype地址。所以man的属性自然是undefined。
但这并不代表不能在new实例之后为prototype赋值,而是不能用对象字面量的方式。如果使用对prototype的属性直接赋值的方式,则不会造成指向错误。
代码如下:

function Person(){}

var man = new Person();

Person.prototype.name = "Tom";
Person.prototype.age = 20;
Person.prototype.saySomething = function(){
    alert("What's up?");
};

console.log(man.name);

可以看到只是将对象字面量换成了“麻烦”点的方式。
结果截图:
这里写图片描述

很容易理解,因为这种方式并没有改变prototype的地址。对象字面量方式虽然简便,但却等于改变了prototype的地址。
所以在实例创建之后,再使用对象字面量方式重写prototype就会使得之前的实例指向的曾经的prototype变得不可联系。比如:

function Person(){}

Person.prototype.name = "John";

var man = new Person();

Person.prototype={
    name:"Mike"
};

Person.prototype.name = "Tom"; 

console.log(man.name);

他的名字会是什么呢?
结果如图:
这里写图片描述
如果不直接给man添加一个自己的name属性的话,他会变成永远的John。
所以对象字面量重写会使得之前创建的实例与之后创建的实例实际指向不同的prototype。慎用之。

你可能感兴趣的:(ECMASript)