原型链的知识,涉及到构造函数(constructor)、实例(instance)、原型对象(prototype),下面将一一讲解(最后还附带instanceof原理~)
什么是构造函数?
在JS中,任意函数都能当做构造函数,实际编码中,一般都有约定俗成的规范,例如:函数名首字母大写;函数名使用名词,而不是动词;一般只会用 new 的方式使用,不会直接调用;and so on...(编不下去了....)。
什么是实例?
一般指通过使用 new 构造函数(),返回的对象。
什么是原型对象?
原型对象没啥概念可讲,先看下面一段代码:
演示代码
构造函数.prototype,这个就是原型对象...
下面再上一张图
构造函数、实例、原型对象关系图
最后再来说说原型链,每个对象都有一个特殊的属性proto,proto指向这个对象的构造函数的原型对象,以演示代码为例,Person是构造函数,p是实例对象,p.proto === Person.prototype为true(演示代码第7行),由于prototype即原型对象也是一个对象,它也有proto属性,这样就形成了一个链条,也就是原型链,原型链的顶端为Object.prototype。
原型链有什么用?
模拟继承,OOP的关键,暂时就讲这么多,以后再细讲。
instanceof原理
原理示意图
检测实例对象的原型对象与构造函数的原型是否是同一个对象,如果不是,根据实例对象的原型链依次查找,直到相等,或者到达原型链顶端。
上面文字可能表达的不是很清楚,下面上代码:
function myInstanceOf (obj, constructor) {
// 对象的原型对象
let objProto = Object.getPrototypeOf(obj);
// 构造函数的原型对象
let constructorProto = constructor.prototype;
if (objProto === constructorProto) {
return true;
} else {
while (objProto = Object.getPrototypeOf(objProto)) {
if (objProto === constructorProto) {
return true;
}
}
return false;
}
}
function Person (name) {
this.name = name;
}
Person.prototype.hi = function () {
console.log(`Hi, My name is ${this.name}`);
};
let p = new Person('Monkey');
p.hi();
console.log('------------------------------------------------');
let other = {name: 'Lucy'};
console.log(`p is myInstanceOf Person : ${myInstanceOf(p, Person)}`);
console.log(`p is myInstanceOf Object : ${myInstanceOf(p, Object)}`);
console.log(`other is myInstanceOf Person : ${myInstanceOf(other, Person)}`);
console.log(`other is myInstanceOf Object : ${myInstanceOf(other, Object)}`);
console.log('------------------------------------------------');
console.log(`p is instanceof Person : ${myInstanceOf(p, Person)}`);
console.log(`p is instanceof Object : ${myInstanceOf(p, Object)}`);
console.log(`other is instanceof Person : ${myInstanceOf(other, Person)}`);
console.log(`other is instanceof Object : ${myInstanceOf(other, Object)}`);</pre>
使用myInstanceOf和instanceof的结果是一致的