# 原型
# prototype
每一个函数都具有prototype属性,即原型
function F() {}
console.log(F.prototype); // {constructor: ƒ}
这个prototype属性返回的是一个对象,是构造函数所创建实例的原型对象。
function F() {}
console.log(new F().__proto__ === F.prototype); // true
# constructor
每一个原型都有个constructor指向关联的构造函数
function F() {}
console.log(F === F.prototype.constructor); // true
console.log(F === new F().constructor); // true,由于实例没有constructor属性,则向上找原型的constructor属性
# __proto__
每一个对象都有__proto__属性,即隐式原型,指向创建该对象的函数的prototype
Object.prototype.__proto__ === null; // 比较特殊
Function.__proto__ === Function.prototype; // Function也是对象,也是函数,所以会被Function创建
Function.prototype.__proto__ === Object.prototype;
// Object.getPrototypeOf(foo) 根据实例对象获取原型对象
# 继承
- 原型链继承: 引用值共享问题
- 构造函数继承: 无法拿到原型上的方法
- 组合继承: 调用两次构造函数
- 寄生组合继承:Object.create
两种不好的使用:
// Bar.prototype会直接引用Foo.prototype,一旦修改Bar.prototype.name,则会修改Foo.prototype对象
Bar.prototype = Foo.prototype;
// 引用值共享问题。
Bar.prototype = new Foo();
目前比较好的:
// ES6 之前需要抛弃默认的 Bar.prototype.相当于Bar.prototype.__proto__ = Foo.prototype
// Object.create()的参数就是指向生成对象的原型
Bar.ptototype = Object.create(Foo.prototype);
// 一种polyfill
if (!Object.create) {
Object.create = function(o) {
function F(){} F.prototype = o;
return new F();
};
// ES6 开始可以直接修改现有的
Bar.prototype Object.setPrototypeOf( Bar.prototype, Foo.prototype );