打一个小广告,作者本人开发的一个集合优质编程教程与视频的网站(包含大量慕课网体系课与实战课),感兴趣的同学可以看一下,青苹网 www.qingp.net
js中,Function的本质是什么?
Object的本质又是什么?
js中有几条原型链?
javascript的语言基于原型链,而实际上js的有两条原型链。开发者主要用到的是图中的红色原型链,如给Array.prototype.xxx=yyy,那么就可以[...].xxx,数组实例对象就继承了其构造函数原型对象中的数据,当然实践一般不会给修改Array这类构造函数的原型对象,最多的就是自定义构造函数,然后给自定义的构造函数定义原型对象,那么这个构造函数的所有实例对象也就都继承了原型对象中的数据。这就是图中红色原型链的所表示的。
那么Array.prototype和自定义构造函数function f(){}的prototype的原型对象是从哪里来的,是谁创造了它?
诸如Array.prototype.xxx=yyy,这实际上就是引用了Array的原型对象prototype而已,也就是它的原型对象就已经存在了,然后才让其能够被引用到。
包括Array.prototype,还是String.prototype,还是Object.prototype,还是Function.prototype,还是自定义构造函数function f(){}的prototype,它们都不是开发者创建的,而是Function构造函数在创建其他构造函数时,用Object()创建的。
可以说Function构造函数是javascript世界中的万物之主,像盘古开天辟地创建了javascript的语言世界和运行机制。而OBject的本质就是用于创建原型对象。
Function构造函数内部有一个this.prototype=new Object(),当Function造物时,就同时通过这句this.prototype=new Object(),给这个物赋予了灵魂。而Object在javascript中的本质也就在于此,作为Function手中的魂灯,赋予其创建的物体灵魂,也就是给予它原型对象,让它能够通过原型对象,能够从上面继承和吸收能量。
Function构造函数,创建了Array构造函数,同时通过new Object()给其创建了prototype对象,因此有Array.prototype。然后[1,2,3]就是由Array构造函数创建,因此[1,2,3]数组实例对象,继承了Array构造函数中的数据,同时继承了Array.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()。
对于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。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。