原型
什么是原型?
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]
来代替)
整体的起源过程如下:
- 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
,然后String
、Number
、Boolean
、Array
这些物种也是如此。 - 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;