共计 1981 个字符,预计需要花费 5 分钟才能阅读完成。
作为从前端刀耕火种年代走过去的物种 -js 原型,原型链,我示意当初高程看了不下三五遍也没能真正消化他,emmmmmm…… 不说了,我辈当自强,一个字,就是干 ……
就从构造函数说起吧
几个基本概念
-
constructor: 失常状况下它会指向对象的构造函数,但这个属性很易扭转,比方你通过字面量形式重写了构造函数的 prototype
function F (){} var f = new F() f.constructor === F // 当初指向正确 ------------------------- 强势宰割 ------------ -------- F.prototype = {.....} f.constructor === F // false 当初 constructor 指向变了, f.instanceof === F // true 用 instanceof 判断更稳
- 对象都有
__proto__
属性,包含函数,但只有函数才有 prototype 属性,函数被定义时它就存在了
- 对象都有
构造函数
function Foo () {this.num = 0}
console.dir(Foo)
Foo.prototype.constructor === Foo // true
在打印的后果外面能够看到构造函数 Foo 领有 prototype 属性,外面蕴含的有 constructor 和 __proto__
属性。Foo 的这个 prototype 属性便是它的原型对象,咱们能够看到函数领有一个 prototype 属性,生下来就领有的。另外要留神的是原型对象(即 Foo.prototype)的 constructor 指向构造函数自身。
这里波及到 new 运算符的一个毛病,用构造函数生成的实例对象,无奈共享属性和办法,起初为了解决这个问题,js 的设计者 Brendan Eich(布兰登·艾克)为构造函数引入了 prototype 属性,须要共享的属性和办法能够放到 prototype 对象里,算是欠缺了 js 的“类”。
prototype, __proto__
Foo.prototype.add = function (x) {this.num += x}
console.dir(Foo)
var foo1 = new Foo()
console.log(foo1)
咱们给 Foo 的原型对象挂载一个 add 办法,并创立一个它的实例 foo1
构造函数 Foo 的原型对象上变领有了 add 办法,同时,打印进去的 foo1 也有 add 办法,认真看,foo 的 __proto__
属性和 Foo 的 prototype 貌似一样啊,验证一下
相等,这阐明了实例的 __proto__
它会指向构造函数的原型对象,foo1 的构造函数也就是 Foo,所以上面这两个是成立的。
foo1.constructor === Foo // true
foo1.__proto__ === foo1.constructor.prototype === Foo.prototype // true
当咱们拜访 foo1.add()办法时,foo 对象自身不具备 add 办法,但它通过 proto 向上找到了他原型对象,所以能应用 add 办法,那如果 Foo 的原型对象上没有 add 这个办法怎么办?Foo 作为一个对象也会有它本人的 __proto__
属性,通过 __proto__
属性 Foo 能够拜访到他构造函数的原型对象,这种顺着 __proto__
层层向上查找的链条机制,就是原型链。实例通过 __proto__
链接到它构造函数的原型对象,而 Foo 函数作为对象也会有它本人 __proto__
属性,始终往上。
如上图,相似这样, 这个链条向上最终会指向 Object 的原型对象,在向上就是 null
总结一下:prototype 外面寄存了一些共享的办法,而 js 正是通过 __proto__
和prototype
实现了原型链,以及对象的继承
Function、Object 关系
像平时的 String,RegExp, Number 等函数都是继承 Function 而来
咱们晓得 Function 属于对象,而 Objcet 也属于构造函数
Function.__proto__ === Object.prototype // true
Object.__proto__ === Function.prototype // true
那么谁是老大呢,这个问题太容易被绕了.
在 ES 标准外面,Function 继承 Function 自身,Function.prototype 继承 Object.prototype
Function.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
所以下面是成立的,也就是说 Function.__proto__
和 Function.prototype 指向是雷同的,都指向了 Object.prototype, 食物链的最顶端就是它了。