Javascript中Function与Object的关系

(Javascript是ECMAScript的一种方言,在下面的描述中,不做区分。)

Javascript是一种面向对象语言,其但和C++、Java这种OO语言不同,JS的OO是通过原型链来实现。关于JS的原型链,已经有很多的文章描述过了。在这里描述的,则是关于Javascript中Function与Object的原型链的关系。

当我们谈论Javascript中的“对象”时,不仅仅是Object,因为它本身也是对象的一种。在Javascript的基本类型(undefined、boolean、null、string、number、object、symbol)中,object指的是我们一般意义上的“对象”,是一种类型,而不是我们在这里要说的Object类型的对象。

在Javascript基础对象中,有一些是最常用的,包括Object、Function、Array、Date。它们都是对象,那么他们的关系是怎样的呢?(在这里,我们探讨一下Object与Function的关系)

记得以前,有人跟我讲过,说Object和Function是互相继承。感觉说的好像很有道理呢。Object是函数,Function是对象。实际上,他们并非相互继承。

对于Object和Function,我们一般指的是他们的构造函数,因为global object(全局对象,在浏览器环境指window)的Object和Function属性的初始值,就是Object constructor和Function constructor。

对于Javascript对象,标准定义了许多的内部槽(internal slot),比如[[prototype]],我们可以通过__ptoto__属性来访问。这和prototype属性并不是一个概念。而这正式Javascript的原型链的实现基础。

关于Object和Function的关系,我们可以用下面这样一张图来进行描述。

如图所示,对象原型链的尽头是null,这并不意外。箭头指向的地方,是属性关系。而以%包裹的是Javascrpit的固有对象(intrinsic object)。从图可以看到,有两个很重要的固有对象:

  • %ObjectPrototype%
  • %FunctionPrototype%

这两个固有对象,通过一定的属性包含关系,形成了Function与Object的拓扑图。需要说明的一点的是,%FunctionPrototype%对象没有prototype属性。

Function和Object并非相互继承,它们都有一个共同的祖先,%ObjectPrototype%,这才导致了他们有一些共同的属性和性质。

那么,为什么Object又是函数呢?很简单,Javascript对象,有[[call]][[constructor]]内部槽,它们决定了js对象是否为callable、以函数进行调用时的行为、是否可为构造函数、以构造函数进行调用时的行为。

PS: 对于图上的关系,我们可以用以下代码做简单的验证

1
2
3
4
Function.prototype === Function.__proto__
Function.prototype === Object.__proto__
Function.prototype.__proto__ === Object.prototype
Object.prototype.constructor === Object
坚持原创技术分享,您的支持将鼓励我继续创作!