js原型模式创建对象

我们先看一个正常的例子:

function Person() {
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
alert(this.name);
};

let friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //true
alert(friend.constructor == Object); //true

可能有些代码洁癖者看到这么多重复的 Person.prototype 会有点受不了,那就简单地改写一下:

function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
    }
};

我们将 Person.prototype 设置为等于一个以对象字面量形式创建的新对象。
但是,问题来了:

var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false 
alert(friend.constructor == Object); //true

friendconstructor 不再指向 Person 了,查了一些资料发现:

在调用构造函数的时候,会为生成的新的实例对象添加一个指针指向构造函数的原型对象

那么在重写prototype的时候我们用对象字面量的方式创建了一个新的对象,而用这种方式创建就相当于调用了Object构造函数,写个例子看看:

    const o1 = {}
    const o2 = new Object()
    
    console.log(o1.__proto__ === o2.__proto__)    // true

知道了问题所在,那就在原来基础上手动指定 constructor 就好了:

Person.prototype = {
constructor : Person, // 在这里指定
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
    }
};
alert(friend.constructor == Person); //true 

大功告成!
但是....到这里还没结束。我们知道,调用构造函数时会为实例添加一个指向最初原型的[[Prototype]] 指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。

function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
    }
};
friend.sayName(); // Uncaught TypeError: friend.sayName is not a function at <anonymous>`

这里就找不到原型对象上的sayName方法了!

image.png

在修改了构造函数的原型对象之后,即使给原型对象添加了constructor属性,但是之前通过构造函数生成的实例对象不会自动更新它们的原型对象的指针。
既然如此,那我们就在重写原型对象之后再生成Person的实例不就好了吗?
来看看

function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
    }
};
var friend = new Person();
friend.sayName(); // Nicholas (成功!)

image.png

OK ~~~~

阅读 188

推荐阅读
前端手记
用户专栏

0 人关注
1 篇文章
专栏主页