JavaScript 的基本类型是数值类型、字符串类型、布尔类型、null 和 undefined,除此之外所有其他类型都是对象:数组是对象、函数是对象、正则表达式是对象,当然对象也是对象(在后端程序员的 JavaScript 之旅 – 好的设计与坏的设计 一文中,我们了解到甚至 null 也是对象)。对象系统是 JavaScript 的根基,基于原型的面向对象设计巧妙地隐藏了内部的原型链的实现,让使用者容易上手,然而想对其做进一步的了解会产生许多疑惑。
我们知道,一个普通对象(非函数对象)是通过原型链实现面向对象的,那么函数对象作为一个对象,它的原型链指向什么? Function 函数对象和 Object 函数对象之间又有什么联系? 好在我找到 JavaScript Object Layout 一文对 JavaScript 的对象系统画了一张很直观的图,可以帮助我们理解。
要点
- 对象通过
__proto__
属性指向其构造函数(函数对象)的prototype
属性实现继承。 - 构造函数的
prototype
属性实际上是包含constructor
属性的对象,该constructor
属性指向构造函数。 - 构造函数(函数对象)本身并不使用
prototype
属性做原型链,供其创建出来的对象使用。 - 构造函数默认的
prototype
属性可以被改写,这时候其创建的对象继承这个被改写后的属性。 - Function 对象比较特殊,Function 的
__proto__
指向Function.prototype
,换句话说是 Function 自己构造了自己。 Object instanceof Object === true
,但是Foo instanceof Foo === false