原型和原型链
原型的特性
- 所有的引用类型(数组、对象、函数),都对象特性,即可自由扩展属性(除了“null”意外)
- 所有的引用类型(数组、对象、函数),都有一个_proto_(隐式原型)属性,属性值是一个普通的对象
- 所有的函数,都有一个prototype属性,属性值也是一个普通的函数
- 所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的 prototype(显性属性)属性值
- 每一个原型对象都有一个constructor属性指向关联的构造函数;
- 原型链的链接依赖proto这个指针,每一级的原型对象都依靠这个指针指向上一级原型对象;
- 原型链的尽头始终是null;
- 原型对象充当两面派,既是构造函数函数,也是对象;
function Foo() {
}
const obj = new Foo();
console.log(Foo.prototype === obj.__proto__);
console.log(obj.constructor === Foo);
console.log(Foo.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__ === null);
console.log(Object.constructor === Function);
true true true true true
原型链的形成
每个对象拥有一个原型对象,通过 _proto_ 指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null,这种关系被称为原型链
- [图片上传失败...(image-e66217-1555428386290)]
instanceof 运算符
instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。 原理就是一层一层查找 _proto_,如果和 constructor.prototype 相等则返回 true,如果一直没有查找成功则返回 false。
构造函数、原型和实例之间的关系
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型对象的指针。
(1)实例对象由构造函数new产生;
(2)构造函数的原型属性与实例对象的原型对象均指向原型
(3)原型对象中有一个属性constructor指向对应的构造函数