介绍本文之前,请诸位看客忘却之前所学,诸如Java、C++之类。所谓无招胜有招,思维定势往往有时候会阻碍了你的思想。这里给你五秒。5,4,3,2,1。
造物方法论
假设你自己就是上帝,现在你要创造一个世界,这个世界在内存里,而内存里混沌得只剩0和1或者什么都没有。那你该从何开始呢?无非是两个事情,拿什么造和怎么造的问题。所谓方法论,就是用来解释怎么造东西的。为了造这个世界,我们得有个方法。我们先规定一个东西得有个类型,然后规定这个东西得有个值或者一个取值范围。
“在内存里有一串0和1,机器知道这是什么吗?不知道,我们得告诉他,所以规定一个类型,这样机器知道这一串0和1是什么了,比如二进制序列0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110如果看作是64位无符号整数类型就是4643234631018606494 而按照IEEE 754规定的浮点数二进制表示规则的双精度浮点类型则是257.331。
“ ——所谓类型
万物始于空
有了怎么造东西的方法,我们拿什么开始造东西?答案是从“空”开始。混沌伊始,万物皆空,视为Null(注意首字母大写)。这个Null是个类型,总得给他个值,于是就有了null(注意首字母小写)。所谓空即是空,Null即是null。
万物皆对象
这个世界的一切实体都应该是对象。那我们就先造个Object吧。万物皆对象,类型也是对象,Object对象的类型就是Object,取值范围是万物。可是问题来了,从哲学层面上我们要回答这三个问题,“我是谁,我从哪里来,我到哪里去”。我是Object,但我从哪里来呢?于是,我们要给Object设定一个属性Object.prototype,类型是Object,取值范围是万物。这个prototype就好像Object的户口簿,上面写了父母是谁谁谁,但问题是他可以被篡改。我们需要一个内置的谁也改变不了的属性,那就设个Object.__proto__,他指示了Object真正是谁生的。而且我们规定,只有原型对象,也就是xxx.prototype才能生万物。作为一个对象,Object.prototype从哪里来?他从”空“中来。所以Object.prototype.__proto__=null。我们站在Object.prototype的角度上看,需要回答我到哪里去的问题。让我们来设定一个属性值Object.prototype.constructor,让他来回答这个问题,他等于Object。好了,让我们看看这个世界有什么了?
这里有一个问题,就是Object的__proto__值是什么,这个后面会讲到,他其实是Function.prototype,但并不代表他来自于Function,疑问Function.__proto__指向了Object.prototype。
构造世界
头七天,我们构造出了对象,现在我们可以开始构造些山啊水啊。你要用数字?好的,那我们来弄个类型对象Number,作为大自然,生命诞生之前就已经在那里了。所以Number是内置的(build-in)。你还要用字符串?好的,那来个String类型对象吧。还要布尔值?还要数组?so easy,来个Boolean,来个Array。另外我还想要个空,来表达我的钱包是空的,我的手机里没电池,怎么办?没关系,我们造个Undefined类型,他的值定为undefined就好了。
山水都有了,好开心,问题是这山这水似乎没有生气,那么我们让他们动起来,定义一个Function类型对象吧,他从哪里来,设定一个Function.prototype,prototype又从哪里来?Function.prototype.__proto__等于Object.prototype。这样看起来Function就是Object生的了。Function.prototype要去向哪里?Fucntion.prototype.constructor=Function。另外我们让Object.__proto__等于Function的原型对象,即Function.prototype。好了,这个世界生动了,然后我们看看现在有了什么?
创造生命
有了活泼的山水了,我们还需要生命,那些活的东西。来条狗吧。先搞个狗的类型对象,var Dog = function(){};然后实例化一条狗var dog = new Dog(); 狗对象dog来自于狗类型Dog,所以dog.__proto__=Dog.prototype,dog还需要一个构造器,于是dog.constructor=Dog。世界越来越复杂了,让我们直接看图说话。
又七天,我们创造了世界,构造了万物。当你想使用一个对象的时候,只要看上图的左半边,那就是所谓的prototype链。你想让所有的狗都会叫,那就在Dog.prototype里加函数,Dog.prototype.shout=function(){};因为每条狗都是Dog.prototype生出来的。
图中我们可以看出一个规律,__proto__都是指向prototype的,说明不管是类型对象,还是普通对象,都是来自原型对象的,而constructor中文名字叫构造器,指示了构造该对象所使用的方法论,他都是指向类型对象的,我们定义类型对象的时候,就是定义了一个函数。而终极构造器,就是Function。
至此,我们造出了一个世界,然后去这个世界里探险吧。
The end。