原型
原型总的来说就两点:
- 构造函数拥有 prototype 属性,它指向的对象被称为原型对象,原型对象拥有 constructor 属性,指回构造函数。构造函数的实例拥有
__proto__
属性,指向构造函数的 prototype;构造函数同时可以是实例对象,所以也拥有__proto__
属性。这就形成了原型链。 - 属性查找:对象首先在本身查找相应属性,如果找不到,就会往上遍历原型链查找。
原型链
instanceof
function Foo() {}
Object instanceof Object; // true
Function instanceof Function; // true
Number instanceof Number; // false
String instanceof String; // false
Function instanceof Object; // true
Foo instanceof Function; // true
Foo instanceof Foo; // false
原理
one more time!
instanceof
function myInstanceof(left, right) {
if (typeof left !== "object")
throw newError("instanceof left-value can't be primitive");
let proto = left.__proto__;
let prototype = right.prototype;
while (true) {
if (proto === null) return false;
else if (proto === prototype) return true;
proto = proto.__proto__;
}
}
继承
- 原型链:不能传参、共用引用类型
- 盗用构造函数:原理是使用 call,缺点是函数不能复用、不能访问父类原型方法
- 组合继承:
call
+new SuperType()
,调用两次父构造函数 - 原型式继承:被规范为
Object.create
,不需要单独创建构造函数,缺点还是共用引用类型 - 寄生式继承:
Object.create
+ 工厂模式,添加的方法无法复用 - 寄生式组合继承:解决两次调用父构造函数问题
function inheritPrototype(subType, superType) {
let o = Object.create(superType.prototype); // 创建对象 o.__proto__ == superType.prototype
o.constructor = subType; // 增强对象 superType.prototype.constructor == superType
subType.prototype = o; // 赋值对象
}
寄生组合继承的原理
小结
原型其实就两点
- 实例的隐式原型指向构造函数的显式原型
- 属性查找会沿着原型链向上而行
- 继承方式和对应缺点