19

以“一个公式” 的角度理解原型链

 4 years ago
source link: https://segmentfault.com/a/1190000021762334
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

米娜桑,哦哈哟~

原型链,已经是一个老生常谈的话题了,这里就不过多总结,精华一张图就可以搞定。该文章更多的是从 一个公式 的角度讲述原型链。

补充说明

实例化:用类( class )创建对象( obj )的过程。如:

TensionMax = new Person() ,那么 TensionMaxPersion 的实例(对象)。

但由于 JavaScript 并不存在类,所以 JavaScript 所谓的类,只是我们模拟出来的函数,最终还是基于原型构建。

以下 3 个观点只是为了更方便快捷地理解原型链,切勿对号入座。其中依然存在着先有鸡还是先有蛋的问题。对于单纯的开发者来说,感兴趣或者时间充裕的话可以深究,已附上友情链接于本章结尾。

先上结论

1、 obj.proto === class.prototype

满足此式子时,我们可以把 obj 称之为 class 实例出来的对象。

2、 obj 上属性的查找会以 __proto__ 链条的方式进行查找,直到为 null 时终止。

3、以第 1 点为理解导向,原型链的终点是 Object.prototype

1、class.prototype === obj.__proto__

这条就当作是一个公式。满足这一条,那么我们可以把 obj 当作 class 实例出来的对象。

当我们实例出 Personlet Tension = new Person() ,其中的关系图如下:

MVnaua6.png!web

let Person = function (name, age) {
    this.name = name
    this.age = age
    this.race = 'human'
}
Person.prototype.country = 'China'

console.log(Person.prototype) 
//输出{country: 'China', constructor: Person}

也就是说 Person.prototype.constructor === Person

创建函数时,函数会自带特有的属性 prototype

而当实例 Persion

let TensionMax = new Person('huang', 10) 

console.log(TensionMax) //{name: 'huang', age: 10, race: 'human'}
console.log(TensionMax.country) //China
console.log(TensionMax.__proto__.country) //China

换句话而言, new 操纵符 实际做了以下的事情。

let TensionMax = {} //即 new Object()
TensionMax.__proto__ = Person.prototype

Person.call(TensionMax)
//call在这里的作用是将 Person 的 this 值拷贝到 TensionMax 对象中。

也就是说,当实例化对象后,对象 TensionMax 和对应的类 Person 通过 __proto__ 来链接。

2、obj 的属性会以 "__proto__" 链条的方式进行查找,直到为 null 时终止

根据上述的关系图,如果一直根据 __proto__ 这个链条查找,会有一个终点。

console.log(TensionMax.__proto__.__proto__.__proto__) //null

(TensionMax.__proto__).__proto__ === Object.prototype //true

根据第 1 点的公式, TensionMax.__proto__Person.prototypeObject 函数这个类实例出来的对象。最终到达终点 Object.prototype

YRjqAvR.png!web

console.log(Object.prototype.prototype) //undefined
console.log(Object.prototype.__proto__) //null

3、原型链的终点是 Object.prototype

以第 1 点为理解导向,原型链的终点是 Object.prototype ,那么有如下关系:

Tension为 Person 的实例对象

Person为 Function 的实例对象

Person.prototypeObject

的实例对象

Function为 Function 的实例对象

Object为 Function 的实例对象

Function.prototype为 Object 的实例对象

NF3Ufe6.png!web

根据第 1 点的公式,以 __proto__ 箭头为导向可以看出,先有 Object.prototype ,由之诞生 Function.prototype ,随后才有了 FunctionObject

那么 FunctionObject 谁先有,还有待深究。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK