一、第一类
话说在Javascript中所有人皆第一类,第一类是提及类别的两个示例,在JS中提及类别主要包括:Object、Array、Date、RegExp和Function,除此以外,ECMAScript还提供更多3个特定的提及类别:Boolean、Number、String。
与此相反,第一类是某一某一提及类别的示例,新第一类是透过new运算符后跟两个缺省来建立的,缺省这类是两个表达式,或者说该表达式是所致创建第一类的目地而再次出现的。
红豆:
二、Function类别
要说ECMAScript中什么最有意思,那莫过于表达式了,而有意思的根源在于——表达式实际上也是第一类,可称为表达式第一类。每个表达式都是Function类别的示例,而且与其他提及类别一样具有属性和方法。由于表达式是第一类,因此表达式名实际上也是两个指向表达式第一类的指针
与普通第一类不同的是:
三、蓝本第一类
在第一节说过,缺省可以用来建立某一类别的第一类,像Object、Array这样的原生表达式,运行时会自动再次出现在执行环境中。我们也可以建立自定义的缺省,从而自定义第一类:
缺省建立第一类必须透过new运算符来进行,用这种方式建立第一类会经历以下四个过程:
(1)建立两个新第一类;
(2)将缺省的作用域赋给新第一类(让this指向新第一类);
(3)执行缺省中的代码(为新第一类添加属性);
(4)返回新第一类;
无论什么时候,只要建立了两个新表达式,就会根据一组某一的规则为该表达式建立两个prototype属性,这个属性指向表达式的蓝本第一类。在默认情况下,所有蓝本第一类都会自动获得两个constructor(缺省)属性,这个属性是两个指向prototype属性所在表达式(缺省这类)的指针:
建立了自定义的缺省之后,其蓝本第一类默认只会取得constructor属性;至于其他方法,则都是从Object继承而来的。当调用缺省new两个示例(第一类)后,该示例内部将包含两个指针(内部属性_proto_),指向缺省的蓝本第一类,这个连接存在于示例和构造表达式的蓝本第一类之间,而不是示例和缺省之间:
之前在一篇博文中发现这样的写法:
其实示例这类并没有constructor属性,而是示例透过__proto__指向了Person.prototype,而constructor属性是Person.prototype上的属性,指向缺省这类。
蓝本第一类其实是两个普通的第一类,但是Function.prototype除外,它是两个表达式第一类,但它很特定,没有prototype属性(前面说道表达式第一类都有prototype属性))
四、蓝本链
蓝本链是实现继承的主要方法,其基本思想是:利用蓝本(prototype)让两个提及类别继承另两个提及类别的属性和方法。
回顾一下缺省、蓝本和示例的关系:
(1)每个缺省都有两个蓝本第一类;
(2)蓝本第一类都包含两个指向构造表达式的指针(constructor);
(3)示例都包含两个指向蓝本第一类的内部指针(__proto__)
如第三节所说,JS 在建立第一类(不论是普通第一类还是表达式第一类)的时候,都有两个叫做__proto__ 的内置属性,用于指向建立它的缺省的蓝本第一类。
第一类 person 有两个 __proto__属性,建立它的缺省是 Person,缺省的蓝本第一类是 Person.prototype ,所以:
person.__proto__ == Person.prototype;如果我们让蓝本第一类等于另两个第一类的示例,结果会怎样呢?此时的蓝本第一类将包含两个指向另两个蓝本第一类的指针,相应的另两个蓝本第一类中也包含着另两个缺省的指针。
即是:
假如另两个蓝本又是另两个类别的示例那么上述关系依然成立,如此层层递进,就构成了示例与蓝本的链条。
然鹅,我们都知道,所有的提及类别默认都继承了Object,这个继承也是透过蓝本链实现的。大家要记住,所有表达式的默认蓝本都是Object的示例,蓝本第一类是两个普通第一类,两个普通第一类的缺省是Object。因此默认蓝本都会包含两个内部指针,指向Object.prototype,所以最终的蓝本链:
五、再来说说Function
回头看看第一节,第一类是使用 new 运算符后跟两个缺省来建立的,构造器不仅仅有 Object,也可以是 Array,Date,Function等,既然他们都是表达式,辣么它们的__proto__又指向谁呢?相信聪明的你已经猜到了,是Function.prototype,它是两个空表达式(Empty function)
插一句:JavaScript中有内置(build-in)构造器/第一类共计12个(ES5中新加了JSON),剩下如Global不能直接访问,Arguments仅在表达式调用时由JS引擎建立,Math,JSON是以第一类形式存在的,无需new。它们的proto是Object.prototype。
上面的情况说明了神马?
所有的构造器都来自于Function.prototype,甚至主要包括根构造器Object及Function自身。故所有构造器都继承了·Function.prototype·的属性及方法。如length、call、apply、bind**
Function.prototype也是唯一两个typeof为function的prototype。其它的构造器的prototype都是两个第一类。
大招来了:
知道了所有构造器(含内置及自定义)的__proto__都是Function.prototype,那Function.prototype的__proto__是谁呢?
相信都听说过JavaScript中所有人皆第一类,表达式也是第一类,从哪能体现呢:
这说明所有的构造器也都是一个普通 JS 第一类,可以给构造器添加/删除属性等。同时它也继承了Object.prototype上的所有方法:toString、valueOf、hasOwnProperty等。
最后Object.prototype的proto是谁?
相信到此大家对于第一类、缺省、蓝本、蓝本链、继承都有了比较明确的了解了,再也不用怕各种原型刁难了。辣条在手,天下我有!!!
水平有限,欢迎各位圈内大神多多扔砖,多多指正!!
本文借鉴了:
1、《Javascript高级程序设计》