简述原型链

背景
JavaScript 是动静的,自身不提供一个 class 的实现。即使是在 ES2015/ES6 中引入了 class 关键字,但那也只是语法糖,JavaScript 依然是基于原型的

当谈到继承时,JavaScript 只有一种构造:对象。每个实例对象(object)都有一个公有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。该原型对象也有一个本人的原型对象(__proto__),层层向上直到一个对象的原型对象为 null。依据定义,null 没有原型,并作为这个原型链中的最初一个环节。

简直所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

链接:https://developer.mozilla.org...

先说几个名词概念

  1. prototype 显式原型
  2. proto 隐式原型

介绍下 援用类型

  1. 都具备对象个性,即可自在扩大属性。
  2. 都有一个隐式原型 proto 属性,属性值是一个一般的对象。
  3. 隐式原型 __proto__ 的属性值指向它构造函数的显式原型 prototype 的属性值。
  4. 当获取一个对象的某个属性时,如果这个对象自身没有这个属性,那么会去它的隐式原型 __proto__(也就是它的构造函数的显式原型 prototype)中寻找。

看个

function Student(name) {    this.name = name}const stu = new Student('xiaomin')stu.name  // 'xiaomin'// toString 为对象罕用办法,返回一个示意该对象的字符串stu.toString()  // '[object Object]'// 给 toString 赋值stu.prototype.toString = function stuToString() {  return `${this.name}`;};console.log(stu.toString());// expected output: "Gabby"

问题抛出:为什么 stu 一开始没有定义 toString 却能获取到呢?

stu 实例先从本身登程查找,发现没有 toString 办法。找不到,就往上走,找 Student 构造函数的 prototype 属性,还是没找到。因为构造函数的 prototype 是一个对象,那对象的构造函数是 Object ,所以就找到了 Object.prototype 下的 toString 办法。

这里补充阐明下,如果最终都未找到,则返回 undefined。并且此时 Object.prototype 的隐式原型指向 null
tips: null 是为了防止死循环而设置的

stu.xx // undefined


引申一个概念:instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否呈现在某个实例对象的原型链上

function Car(make, model, year) {  this.make = make;  this.model = model;  this.year = year;}const auto = new Car('Honda', 'Accord', 1998);console.log(auto instanceof Car);// expected output: trueconsole.log(auto instanceof Object);// expected output: true

instabceof 实现形式(原理)

// 变量R的原型 存在于 变量L的原型链上function instance_of (L, R) {      // 验证如果为根本数据类型,就间接返回 false  const baseType = ['string', 'number', 'boolean', 'undefined', 'symbol']  if(baseType.includes(typeof(L))) { return false }  let RP = R.prototype;  // 取 R 的显示原型  L = L.__proto__; // 取 L 的隐式原型  while (true) {    if (L === null) { // 找到最顶层      return false;    }    if (L === RP) { // 严格相等      return true;    }    L = L.__proto__;  // 没找到持续向上一层原型链查找  }}

instanceof 判断流程如下:

  1. f 的隐式原型 __proto__ 和 Foo.prototype, 是相等的所以返回 true 。
  2. f 的隐式原型 __proto__ ,和 Object.prototype 不等, 所以持续往上走。f 的隐式原型 __proto__ 指向 Foo.prototype ,所以持续用 Foo.prototype.__proto__ 去比照 Object.prototype, 判断相等返回 true。(因为 Foo.prototype 就是一个一般的对象)

参考链接:https://juejin.cn/post/693449...