简述原型链
背景
JavaScript 是动静的,自身不提供一个 class 的实现。即使是在 ES2015/ES6 中引入了 class 关键字,但那也只是语法糖,JavaScript 依然是基于原型的
当谈到继承时,JavaScript 只有一种构造:对象。每个实例对象(object)都有一个公有属性(称之为 proto)指向它的构造函数的原型对象(prototype)。该原型对象也有一个本人的原型对象(__proto__),层层向上直到一个对象的原型对象为 null。依据定义,null 没有原型,并作为这个原型链中的最初一个环节。
简直所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
链接:https://developer.mozilla.org…
先说几个名词概念
- prototype 显式原型
- proto 隐式原型
介绍下 援用类型
- 都具备对象个性,即可自在扩大属性。
- 都有一个隐式原型 proto 属性,属性值是一个一般的对象。
- 隐式原型 __proto__ 的属性值指向它构造函数的显式原型 prototype 的属性值。
- 当获取一个对象的某个属性时,如果这个对象自身没有这个属性,那么会去它的隐式原型 __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 判断流程如下:
- f 的隐式原型 __proto__ 和 Foo.prototype, 是相等的所以返回 true。
- f 的隐式原型 __proto__ , 和 Object.prototype 不等, 所以持续往上走。f 的隐式原型 __proto__ 指向 Foo.prototype,所以持续用 Foo.prototype.__proto__ 去比照 Object.prototype, 判断相等返回 true。(因为 Foo.prototype 就是一个一般的对象)
参考链接:https://juejin.cn/post/693449…