这里先简单介绍一下我研究这个问题的初衷。起初我只是想研究一下原型链的基本思想。构造函数拥有prototype属性,指向它的prototype,而该构造函数的实例化对象则拥有一个[[prototype]]属性,或者说__proto__属性,同样指向该构造函数的prototype。所谓prototype,我个人把它理解为Java语言的类概念中的方法或是常量的集合,JS语言设计者之所以这么做,我想是因为考虑到对象的本质问题。对象的存储只涉及到其拥有的变量(这在对象序列化中体现的淋漓尽致),因为方法这种不变的共有的东西无需携带,只需放在类里。JS和Java语法虽然有差异,但是所遵循的OO思想本质上并无不同。所以我认为,JS的prototype就是实现了这么一个构造外的机制,而构造函数实现了真正的变量赋值功能以及初始化功能。但是,仅仅只是这样吗?NO!虽然核心的原理就这些,但是JS还拥有一些附加的属性在构造函数和对象上,这些属性就是JS独特的魅力与灵活性所在。因此,当我一路追寻下去时,终于发现了存在于JS中的构造函数与对象之间的“猫腻”,而这次的所有发现都是基于原型链所展开的。下面将把我所看到的现象展示出来,它们的确有趣的很。
同样是构造函数,普通的Person构造仍然是Function的一个实例对象;而Function构造,是原本就有的,JS内置的包装类,它同时也是一个对象,且称为函数对象,JS中一切皆对象的思想在这里体现的淋漓尽致。没错,JS就是这样一种语言,质朴而纯洁,丝毫不会掩饰什么,如果你看不懂它,只因为你没有坦然面对自己罢了。继续,Person函数的__proto__属性也指向Function.prototype对象。也就是说,所有的函数,包括Function构造函数在内,其终极__proto__属性都是指向Function.prototype的。只有Function.prototype对象的__proto__指针才指向Object的原型。
从以上运行结果可以看出:所有的函数,包括浏览器实现或是定义的类的构造函数,包装类等,甚至于Object函数——一切构造函数的__proto__指向都是Function.prototype。这样看来,Function俨然成就了一番“一统天下”的气象,然而,它只不过是一人之下,万人之上,与Object之间也是伯仲之间,虽然它是Object的实例,但是Object对象的构造又属于Function的实例。可谓,你中有我,我中有你,水乳交融,十分亲密。其实话又说回来,本质上这些概念与Java中的.class很类似,都是Class对象,都是Function对象,Class是Object,Function.prototype又是Object,诸如此类概念,随处可见,仅此而已。JavaScript之所以以Java开头,的确是有缘故的。最后,我们还是要说一个共同的终极话题。终究呢,如一句名言所说——“万物皆归于无”。Object.prototype就已经到顶了,这是我们所能接触到的,所能看到的。若穷其理,再追究下去,Object.prototype.__proto__就指向了null,最终指向了空。