原文链接:https://ssshooter.com/2021-01...

用了这么多年的 JavaScript,对于原型链这货色盲目是了解了,然而日常工作中很少应用的“继承”局部最近忽然想起来竟感觉有点生疏,所以在这里略微理一下思路。

本文90%不能让不懂原型链的人看懂原型链,然而可能能够给懂一点原型链的人一点提醒,不过如果本文让你更凌乱的话,请在评论区提出疑难 ????

prototype

只有函数有 prototype,对象没有。

// 函数function A(){}A.prototype// 会输入相似上面的货色{    constructor: A,    __proto__: Object}// 对象a = {}a.prototype // 输入 undefined// 而如果你给一个对象赋予 prototype,成果不过是多了一个 prototype 属性

proto

__proto__ 能够看成一种“连贯”,所到之处的属性(property)都能够拜访。刚进坑的时候据说 __proto__ 不是规范的属性,可能会有不同的实现,但这么多年过去了仿佛也就只用 __proto__

a = { c: 1 }a.hasOwnProperty('c') // 输入 true

a 显然没有 hasOwnProperty 这个属性,于是他会往 __proto__ 找,在 Object.prototype 下找到 hasOwnProperty 并应用。

个别,一个 __proto__ 会被连贯到一个 prototype,但你仍能够间接定义 __proto__

a.__proto__ = { b: 'b' }a.b // 输入 b

所谓的原型链就是由 __proto__ 串成。

例如一只猫let mona = new Feliscatus()     __proto__                   __proto__                     __proto__mona -----------> Cat.prototype -----------> Felis.prototype -----------> Felinae.prototype|                  |                           |                             || 实例本人的属性      | constructor Cat           | constructor Felis           | constructor Felinae                    | 其余绑定在 prototype 的属性  | 其余绑定在 prototype 的属性   | 其余绑定在 prototype 的属性上一层找不到的货色就沿着 __proto__ 往下找,直到止境,找不到就是 undefined 了

__proto__ 也能够间接连贯到一个对象(换句话就是,继承一个对象的属性):

const person = {  isHuman: false,  printIntroduction: function() {    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`)  },}let me1 = {}me1.__proto__ = person// 这样 me1 就能应用 printIntroduction// 不过还有更不便一点的办法,应用 Object.create,这样就不必本人连贯let me2 = Object.create(person)

实例化

new 一个对象时,实际上做了什么,如何本人写一个 new(据说面试会考,不过我没遇到过):

function Person(name) {  this.name = name}Person.prototype.say = words => words// 这是一个人类let person1 = new Person('Lilas')// 失常用 new 的后果是// 1. 返回一个对象,// 2. 这个对象运行了构造函数,// 3. 这个对象能够应用 Person 的 prototype 的属性// 晓得了这三步,上面写一个本人的 newfunction createInstance(klass, ...arg) {  // 返回一个对象  let obj = {}  // 以对象为 this 运行构造函数 klass  klass.call(obj, ...arg)  // 为了让 obj 能够应用 Person.prototype 应用 __proto__ 连贯  obj.__proto__ = klass.prototype  // 返回这个对象  return obj}

继承

下面说过用 Object.create 继承一个对象的属性,这里的继承说的是“类”继承。

JavaScript 在 ES6 之前,其实没有类,所谓的继承就是沿着原型链拜访父类(精确来说是 constructor)的变量和办法。

(顺带一提,想要理解 ES6 之后的类能够看看 Class 继承与 super,从这篇文章还能够看出,ES6 的类不是单纯的语法糖)

在 proto 局部阐明了原型链的构造,上面讲讲实际上怎么结构原型链。

// 下面曾经有一个 Person 了,上面继承 Person 写一个 Boxerfunction Boxer(name, id) {  // 在成为格斗者前他得是集体,所以先调用 Person 构造函数,相当于 super()  Person.call(this, name)  //   而后为这个格斗者加上本人的格斗者 id  this.id = id}// 增加 Boxer 本人的办法Boxer.prototype.punch = () => 'punch!'// 接通到 Person.prototypeBoxer.prototype.__proto__ = Person.prototype

无论接着还要继承多少次,总之,记住 __proto__ 串通了父子的 prototype 就好了。