重学原型与原型链

151 阅读3分钟

原型

什么是原型?

Object.prototype就是原型,它是一个对象,我们也称它为原型对象。

原型的作用是什么?

原型的作用就是共享方法,不会重新开辟空间存储方法。

原型中this的指向是什么?

原型中this的指向是实例。

原型链

什么是原型链?

__proto__是构成原型链的重要属性,原型与原型层层相链接的过程即为原型链。

注意Object.prototype.__proto__已经从 Web 标准中删除,已废弃

警告:Object.prototype.__proto__ 已被大多数浏览器厂商所支持的今天,其存在和确切行为仅在ECMAScript 2015规范中被标准化为传统功能,以确保Web浏览器的兼容性。为了更好的支持,建议只使用 Object.getPrototypeOf()

原型链应用

对象可以使用构造函数prototype的原型对象的属性和方法,就是因为对象通过__proto__链接访问的构造函数prototype的原型对象的属性和方法。

function Star(name,age) {
    this.name = name;
    this.age = age;
}
Star.prototype.dance = function(){
    console.log('我在跳舞',this.name);
};
let obj = new Star('张萌',18);
console.log(obj.__proto__ === Star.prototype); // true

原型与原型链解析

这样有个JavaScript 诞生的故事线,所以这里有个本文的剧场版《JavaScript 世界万物诞生记》,感兴趣的小伙伴可以去看一下,这里看下如图:(注:__proto__写起来太麻烦了,后面我们用[p]来代替)

image.png

整体的起源过程如下:

  • JS 说,我好寂寞。因为 JS 的本源是空的,即:null。
  • JS 说,要有神。所以它通过万能术 __proto__ 产生了 No1 这号神,即:No1.__proto__ == null
  • JS 说,神你要有自己的想法啊。所以神自己想了个方法,根据自己的原型 prototype 创建了对象 Object,即:Object.prototype == No1; No1.__proto__ == null。于是我们把 prototype 叫做原型,就好比 Object 的原型是神,男人的原型是人类一样,同时 __proto__ 叫做原型链,毕竟有了 __proto__,对象、神、JS 之间才有联系。这时候 Object.prototype.__proto__ == null
  • JS 说,神你要有更多的想法啊,我把万能术 __proto__ 借你用了。所以神根据 Object,使用 __proto__ 做了个机器 No2,即 No2.__proto__ == No1,并规定所有的东西,通过 __proto__ 可以连接机器,再找到自己,包括 Object 也是,于是 Object 成为所有对象的原型Object.__proto__.__proto__ == No1,然后 StringNumberBooleanArray 这些物种也是如此。
  • JS 说,神你的机器好厉害喔!你的机器能不能做出更多的机器啊?神咧嘴一笑:你通过万能术创造了我,我通过自己原型创造了对象。如此,那我造个机器 Function,Function.prototype == No2, Function.__proto__ == No2,即 Function.prototype == Function.__proto__ 吧!这样 No2 就成了造机器的机器,它负责管理 Object、Function、String、Number、Boolean、Array 这几个。

从这张图中,我们发现:所有的函数(包括Function)的原型都是No. 2对象,而同时Function.prototype也是No. 2对象。这说明了:

从逻辑上,我们可以认为所有机器(包括Function自己)都是由Function制造出来的。

同时,如果再仔细瞧瞧,你会发现:

Object作为一个机器可以看做是有由Function制造出来的,而Function作为一个对象可以看做是由Object制造出来的。

这就是JavaScript世界的“鸡生蛋,蛋生鸡”问题。

这里有点豁然开朗的感觉,能清楚地了解下面几条公式了:

Object.__proto__ === Function.prototype;

Function.prototype.__proto__ === Object.prototype;

Object.prototype.__proto__ === null;

参考

2019 面试准备 - JS 原型与原型链