【Javascript 基础】原型链

392 阅读2分钟

原文:【Javascript 基础】原型链(你的 star 是对我写作的「正反馈」)。

一、当初,为什么要为 JS 设计原型链?

当初,设计 Javascript这门语言时,作者既想该语言拥有「万物皆对象」的优点,又不想加入类的概念来增加语言的复杂度。

因此,作者提出了原型链(prototype chain)的概念,用来「连接」多个对象,使多个对象可以共享同一份变量,让「继承」成为了可能。

二、__proto__、prototype、constructor 各自代表了什么?

  • __proto__: 通常指向当前对象对应的构造函数中的 prototype ,所有的对象都会有这个属性。

这里的「通常」指的是「非JS内置的对象」。而对于「JS内置的对象」,我建议:「硬记」~

  • prototype: 这就是所谓的原型,只有构造函数才有该属性。

  • constructor: 生成当前对象的构造函数,所有对象都有构造函数。

相较于那些枯燥的等式,结合下图,或许能够更快的理清各种的连接关系。

js_prototype_chain

三、JS 对象的寻值逻辑

js_prototype_chain_2

四、几个衍生出来的面试题

  1. 能否写一个与 New 关键字功能类似的 NEW 方法 ?
function NEW(fn) {
  if (!fn.prototype) {
    throw('不是构造函数');
    return;
  }
  var obj = {};
  var args = Array.prototype.slice.call(arguments, 1);
  obj.__proto__ = fn.prototype;
  obj.constructor = fn;
  fn.apply(obj, args);
  return obj;
}

function Dog(name) {
  this.name = name;
}

Dog.prototype.species = 'animal';

var dog = NEW(Dog, '旺财');
console.log(dog.name); // 旺财
  1. 如下代码,输出什么?
function Aoo() {}
function Foo() {}

Foo.prototype = new Aoo();
var foo = new Foo();

console.log(foo instanceof Foo);
console.log(foo instanceof Aoo);

解释:instanceof 除了会判断对象本身的类型,还会判断对象的 __proto__ 的类型,其伪码大致如下:

function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O = R.prototype;// 取 R 的显示原型
 L = L.__proto__;// 取 L 的隐式原型
 while (true) { 
   if (L === null) 
     return false; 
   if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true 
     return true; 
   L = L.__proto__; 
 } 
}

答案:true true