原生的原型链html
function fn(){},fn 为 Function的一个实例,原型链为 null -> Object -> Function -> fn:函数
fn.__proto__ === Function.prototypethis
Function.prototype.__proto === Object.prototypees5
Object.prototype.__proto__ === nullprototype
原型链经过原型(prototype)连接,prototype 就是一个 只有(构造)函数才有的特殊的实例,包含了constructor指针(和__proto__,全部实例都有)指针
以后new出来的普通实例(非prototype)都包含这个prototype(引用名为__proto__):console.log(sonA) // {/* 其余属性 */ __proto__: Son.prototype}xml
举例来讲,对于函数实例,全部函数实例.__proto__ === Function.prototype (经过这个能拿到Function上的通用属性,如bind函数)htm
甚至Function.__proto__ === Function.prototype, Object.__proto__ === Function.prototype 对象
Function instanceof Object // true Function.__proto__.__proto__ === Object.prototype (优先是更具体的函数,而后才做为更抽象的对象,对象永远在原型链较上层)blog
Object instanceof Function // true Object.__proto__ = Function.prototype
原型链继承:
未继承时
console.log(Son.prototype) // { constructor: Son, __proto__: Object.prototype }
原型链继承了Father时,
console.log(Son.prototype) // { __proto__: Father.prototype }父类的一个实例, 经过new Father 或者 Object.create(Father.prototype)生成
须要手动赋予constructor:
Object.defineProperty(Son.prototype, "constructor", {
value: Son,
writable: false
});
console.log(Object.prototype)
{ __proto__: null }
原型链继承,本质就是修改函数的prototype,使其从指向Function变为指向父类;父类的对象恰好符合这个特性
巩固一下上面的知识点,请判断如下比较是否为真:
Object.prototype.__proto__ === null
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
fn.__proto___ === Function.prototype
Object.prototype === Function.prototype.__proto__
Object.prototype === fn.prototype.__proto__
Object.prototype.isPrototypeOf(fn)
Object.prototype.isPrototypeOf(fn.prototype)
Function.prototype === fn.__proto__;
Function.prototype.isPrototypeOf(fn)
Function.prototype.isPrototypeOf(fn.prototype) // false
答案:以上判断若未特殊说明,结果都为真
谈一下new
自定义原型链:基于原型链的继承
Father() {} -> Son() {]
继承的本质是,如何使Son的实例能访问到Father定义的属性
经过原型链,咱们将Son的原型指向Father
Son原型链如今是指向的Function,Son.__proto__ === Function.prototype
咱们但愿Son.__proto__ === Father.prototype
按es5以前的规范,咱们不能直接访问__proto__,那么只能修改prototype (ES5中用Object.getPrototypeOf函数得到一个对象的[[prototype]]。ES6中,使用Object.setPrototypeOf能够直接修改一个对象的[[prototype]])
咱们知道 Father的实例的__proto__指向Father.prototype,那么Son.prototype等于Father的实例就能够
Son.prototype = new Father() 或者
Son.prototype = Object.create(Father.prototype)
这里有一个问题,prototype的constructor属性应该指向构造函数,而这种写法的constructor经过原型链会找到Father,因此须要定义一下constructor
Object.defineProperty(Son.prototype, "constructor", {
value: Son,
writable: false
});
顺便了解一下原型链查找顺序
优先查找对象的,对象上没有则经过__proto__找prototype,还没找到,就找prototype.__proto__, 也就是父类的prototype
好比
对象objA查找hasOwnProperty
objA -> Son.prototype -> Object.prototype -> Object.prototype.hasOwnProperty
函数funcA查找bind
funcA -> Function.prototype -> Function.prototype.bind
PS:对于 const fn = () => {} 这样的箭头函数,不属于原型链的范畴 能够参考 http://www.cnblogs.com/mengff/p/9656486.html