js三大公理:
1、对象.proto===其构造函数.prototype
2、Function函数构造所有函数
3、Object.prototype是所有对象的(直接或间接)原型
首先我来问你几个问题:
{name:'qiu'}的原型是什么?[1,2,3]的原型是什么?Object的原型是什么?
来回答这个问题之前,我们先来解决原型是什么的问题?
我们知道英文的原型在js中有__proto__和prototype,那么具体是哪个呢?
根据上述的问题,我们很容易得出答案,因为{name:'qiu'}和[1,2,3]是没有prototype的,只有函数才有prototype,所以一般我们指的原型就是__proto__
现在我们可以解答问题了,根据公理1,我们可以得出答案:
{name:'qiu'}的原型是其构造函数Object.prototype
[1,2,3]的原型是其构造函数Array.prototype
Object的原型是Function.prototype
我们可以验证一下答案
如果注意细节的小伙伴可能会问,既然所有构造函数(包括Object函数)都是由Function构造的,那为什么说Object.prototype是所有对象的直接或间接原型?不应该是Function吗?
js世界构造顺序
回答这个问题之前我们来捋一捋js的构造顺序
1、首先,js构造的是一个【根对象】,这个根对象的__proto__指向的是null
2、这个根对象创建了一个函数原型和一个Function函数(此时两者都没有具体名字,姑且称Function函数为F吧)
3、把F的__proto__和prototype都指向同一个地址,也就是函数原型的地址。
4、在浏览器的变量名保存空间中,命名F为Function,从此,函数原型名称为Function.prototype。又因为Function也是一个对象,那么js发明者让Function的__proto__指向函数原型,所以也有了Function是由Function构造而来。
5、由Function构建Object函数,Object.__proto__保存的是Function.prototype的地址,Object.prototype保存的是根对象的地址
用一张图表示
现在我们知道,Object.prototype和Object.prototype对象(根对象)并没有直接的关系,只是在名称上做了指向(相当于给根对象加了名字)
所以说Object.prototype是所有对象的直接或间接原型。
构造函数构造对象
使用构造函数构造对象,下面是一个栗子:
function Fun(name){
this.name='qiu',
this.say=function(){
return this.name
}
}
var a=new Fun('qiu')
当new出实例对象a的时候,js做了什么?
我们知道构造函数Fun是Function构造出来的,那么Fun.__proto__必然指向Function.prototype。
此时,构造函数Fun的prototype是什么呢?答案是就是开辟Fun.prorotype的空间,由Fun自己往里面加东西,然后让实例对象a.__proto__指向Fun.prorotype
Fun.prototype.clog =function(){console.log('我是Fun.prototype')}
给构造函数增加原型方法clog,同时也是给Fun函数new出来的所有实例对象都增加公共方法,这种写在原型prototype上的方法好处是合理使用内存。