JS里原型、原型链以及instanceof实现

Tags
函数式编程
JavaScript
CreatedTime
Aug 18, 2022 09:56 AM
Slug
2019-03-27-javascript-second-prototype
UpdatedTime
Last updated August 18, 2022

JS 对象的 __proto__

  • 所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象
  • 所有的函数,都有一个 prototype 属性,属性值也是一个普通的对象
  • 所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的 prototype 属性值
:ES6 的箭头函数没有prototype属性,但是有__proto__属性。
const obj = {}; // 引用类型的 __proto__ 属性值指向它的构造函数的 prototype 属性值 console.log(obj.__proto__ === Object.prototype); // output: true

原型

题目:如何理解 JS 中的原型?
// 构造函数 function Foo(name, age) { this.name = name; } Foo.prototype.alertName = function() { alert(this.name); }; // 创建示例 var f = new Foo("zhangsan"); f.printName = function() { console.log(this.name); }; // 测试 f.printName(); f.alertName();
但是执行alertName时发生了什么?这里再记住一个重点 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找,因此f.alertName就会找到Foo.prototype.alertName

原型链

题目:如何 JS 中的原型链?
以上一题为基础,如果调用f.toString()
  1. f试图从__proto__中寻找(即Foo.prototype),还是没找到toString()方法。
  1. 继续向上找,从f.__proto__.__proto__中寻找(即Foo.prototype.__proto__中)。因为Foo.prototype就是一个普通对象,因此Foo.prototype.__proto__ = Object.prototype
  1. 最终对应到了Object.prototype.toString 这是对深度遍历的过程,寻找的依据就是一个链式结构,所以叫做“原型链”。

instanceof 实现

instanceof是通过原型链来进行判断的,所以只要不断地通过访问__proto__,就可以拿到构造函数的原型prototype。直到null停止。
/** * 判断left是不是right类型的对象 * @param {*} left * @param {*} right * @return {Boolean} */ function instanceof2(left, right) { let prototype = right.prototype; // 沿着left的原型链, 看看是否有何prototype相等的节点 left = left.__proto__; while (1) { if (left === null || left === undefined) { return false; } if (left === prototype) { return true; } left = left.__proto__; } } /** * 测试代码 */ console.log(instanceof2([], Array)); // output: true function Test() {} let test = new Test(); console.log(instanceof2(test, Test)); // output: true