js中,Function的本质是什么?
Object的本质又是什么?
js中有几条原型链?javascript
javascript的语言基于原型链,而实际上js的有两条原型链。开发者主要用到的是图中的红色原型链,如给Array.prototype.xxx=yyy,那么就能够[...].xxx,数组实例对象就继承了其构造函数原型对象中的数据,固然实践通常不会给修改Array这类构造函数的原型对象,最多的就是自定义构造函数,而后给自定义的构造函数定义原型对象,那么这个构造函数的全部实例对象也就都继承了原型对象中的数据。这就是图中红色原型链的所表示的。java
那么Array.prototype和自定义构造函数function f(){}的prototype的原型对象是从哪里来的,是谁创造了它?数组
诸如Array.prototype.xxx=yyy,这实际上就是引用了Array的原型对象prototype而已,也就是它的原型对象就已经存在了,而后才让其可以被引用到。app
包括Array.prototype,仍是String.prototype,仍是Object.prototype,仍是Function.prototype,仍是自定义构造函数function f(){}的prototype,它们都不是开发者建立的,而是Function构造函数在建立其余构造函数时,用Object()建立的。函数
能够说Function构造函数是javascript世界中的万物之主,像盘古开天辟地建立了javascript的语言世界和运行机制。而OBject的本质就是用于建立原型对象。this
Function构造函数内部有一个this.prototype=new Object(),当Function造物时,就同时经过这句this.prototype=new Object(),给这个物赋予了灵魂。而Object在javascript中的本质也就在于此,做为Function手中的魂灯,赋予其建立的物体灵魂,也就是给予它原型对象,让它可以经过原型对象,可以从上面继承和吸取能量。spa
Function构造函数,建立了Array构造函数,同时经过new Object()给其建立了prototype对象,所以有Array.prototype。而后[1,2,3]就是由Array构造函数建立,所以[1,2,3]数组实例对象,继承了Array构造函数中的数据,同时继承了Array.prototype中的数据。prototype
Array.prototype原型对象是由this.prototyoe=new Object()建立的,所以Array.prototype原型对象的构造函数是Object构造函数(也能够是称为对象),Array.prototype原型对象也就继承了其生父Object构造函数中的数据,也同时继承了Object.prototype原型对象的数据。对象
所以,你能够看到,toString()这个方法追根溯源,其实是Object.prototype.toString,在Function建立Array的时候,Object就跟着建立了Array.prototype,它就继承了Object和Object.prototype中的数据,[1,2,3]数组对象由Array建立,所以[1,2,3]也就继承了Array、Array.prototype、Object、Object.prototype中的数据,所以最终才能够调用[1,2,3].toString()。blog
对于String、Boolean等构造函数,仍是自定义构造函数function f(){...}也都是这样。
function f(){...},看上去是你写了这个普通的构造函数,实际上这个普通的函数是Function建立的,你写的这个f函数,因为是Function()实例化出来的(也就是函数的f的构造函数就是Function),那么普通函数f做为Function构造函数的实例对象,那么普通函数f也就会继承Function构造函数和Function.prototype中的数据。
说来诡异的是,也是Function本身建立了本身,正是在在建立本身的时候,经过this.prototype=new Object()给本身也建立了原型对象,就是图中蓝色的原型对象,这个原型对象因为是new Object实例化的,所以这个蓝色的原型对象,也就继承了Object和Object.prototype原型对象中的数据,这样说来,Object的原型对象是原型链条中的最顶层的一个对象,而后原型链往下揪分裂成了两条。
Function.prototype原型对象虽然继承了Object.prototype中的数据,可是它本身还扩展了本身专有的属性和方法,分别是name、length、call()、apply()、bind()这五个,而后因为普通函数f就是由Funciton建立出来的,所以这个普通函数也就继承了Function和Function.prototype中的数据,所以你才可使用f.apply()仍是f.bind(this),也所以才可使用Array.apply(),这就是图中的第二条蓝色的原型链。固然这条原型链中的数据,会被Array仍是String仍是Boolean这类构造函数继承,可是不会被[1,2,3]这些继承,他们不处于同一个链条上。
虽然Function建立了它本身,也建立了Object,但到底它是先建立本身仍是先建立Object就无从得知了。若是Function先建立了本身,那么在它建立本身的时候,还在使用this.prototype=new Object()给本身建立原型对象时,这个Object又是哪里来的,难道Object就已经先存在了?若是Object先于Function存在了,但Funciton都尚未存在,它怎么去建立Object?这究竟是鸡生蛋仍是蛋生鸡无从得知,这也反映了javascript语言底层机制就是混乱的。
也许这一切都很绕,可是只有理解了Function与Object,才能更清晰高屋建瓴的理解本来繁芜繁杂和混乱的javascript。