关于javascript:简述原型链

28次阅读

共计 2007 个字符,预计需要花费 6 分钟才能阅读完成。

简述原型链

背景
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: true
console.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…

正文完
 0