function Person() {} // constructor
let p = new Person() // instance
Person.prototype === p.__proto__ // 指向原型对象
(p.__proto__ | Person.prototype).constructor // 指向构造函数
每一个构造函数都有一个prototype原型对象,原型对象都包含一个指针通过constructor指向构造函数,而实例都包含一个指向原型对象的内部指针__proto__。
来看一个例子:
现在有两个构造函数PersonA和PersonB
我们这样做:
function PersonA() {}
function PersonB(name) {
this.name = name;
}
PersonA.prototype = new PersonB('1m')
console.log(new PersonA().name)
到这里发现我们给PersonB添加了一个属性name后,并将PersonB的实例赋值给PersonA的原型,这个时候访问PersonA实例的name属性,返回值正好是我们为PersonB设置的name值。
总结一下:
如果要使用实例化对象的某个属性,会首先在该对象内部寻找该属性,如果没有就去该对象的原型中查找,如果还找不到,就继续往上查找,一直找到Object,如果还没有就会报undefined,这就JS中介绍的原型链。
搜索轨迹:
new PersonA() → new PersonB() → new PersonB().prototype...→ Object.prototype
咱们再来看一个例子:
现在有两个构造函数PersonA和PersonB
function PersonA() {
this.father = true;
};
PersonA.prototype.getIsFather = function() {
return this.father;
};
function PersonB() {
this.father = false;
// 如果这里删除属性father $1 将输出 true
};
// 继承
PersonB.prototype = new PersonA();
$1 console.log(new PersonB().getIsFather()); // false
在这个例子中,我们通过原型链的关系让PersonB的原型对象继承了PersonA的getIsFather方法,此时PersonB和PersonA的实例将共享PersonA的所有方法。
总结一下:
new PersonB()先会看看自己有没有getIsFather方法,显然是没有的,怎么办呢,它还得去原型对象中找找,其实它的原型对象中也没有,可是呢,由于PersonA的实例化对象赋值给了PersonB的原型对象,所以,访问PersonB的原型对象相当与访问PersonA的实例化对象。
我是底部
如果这篇文章对你有帮助,那真是一件很棒的事,如果内容有什么问题或建议,欢迎在下方留言。😀 😀 😀