JS原型链

471 阅读2分钟

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.prototypeObject.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上的方法好处是合理使用内存。