【问题标题】:In JavaScript, what is the ultimate root, Object or Function?在 JavaScript 中,什么是终极根、对象或函数?
【发布时间】:2012-12-19 04:20:02
【问题描述】:

在 JavaScript 中,Object 是所有实体的根还是 Function 是根?

例如在以下来源objects-functions-and-prototypes-in.html中,首先作者说“Javascript中的每个实体都是一个对象”,后来它说“任何新对象只能作为函数的实例创建(即使你这样做'var a = new Object;', Object 是一个函数 btw)”。据我所知,作者基本上是自相矛盾的。

我在 JavaScript 的许多其他资源中看到了同样混乱的 cmets。在 Java 中这很容易,您知道任何类 Hierarchy 中的第一个实体都是 Object 类,但在 JavaScript 中,我看到的只是混乱。

那么,有人可以澄清一下是对象优先还是函数优先?什么是根。

【问题讨论】:

  • 简单的答案是原型链的根永远是Object.prototype,除了奇怪的用户操作。

标签: javascript function object


【解决方案1】:

你误会了。

Javascript 中的一切(包括所有函数)都是一个对象。

然而,每个对象都是一个函数的实例。 (由对象的constructor 属性指定)

【讨论】:

  • 从技术上讲,并非所有事物都是对象。基元不是对象。
  • 那么基本的 Object 是一个函数的实例是一个 Object 的实例吗?
  • ^ 所以一切都是对象。我们找到了彩虹的尽头! 我的金罐在哪里?
  • @rlemon 我相信它在Object.prototype.[[Prototype]];不幸的是,它是空的。
  • @SLaks,怎么一切都是对象,然后一切都是函数的实例?这意味着一个对象是一个函数,但你刚才说一切都是一个对象,这意味着函数是一个对象。就像我包含的资源的作者一样,您自相矛盾。
【解决方案2】:

我相信该行的结尾是Object.prototype,它是一个对象。这就是让我这么想的原因:

Function.prototype;                    // the empty function object
Function.prototype.__proto__;          // the default Object prototype
Object.prototype;                      // the default Object prototype
Object.prototype.__proto__;            // null

ECMAScript 5.1 规范是这样声明的:

  1. 15.3.4 Properties of the Function Prototype Object:

    Function原型对象的[[Prototype]]内部属性的值是标准的内置Object原型对象

  2. 15.2.4 Properties of the Object Prototype Object

    Object原型对象的[[Prototype]]内部属性的值为null

【讨论】:

  • 我认为你是对的。似乎是 Object.prototype 是层次结构的最终根的可靠证据。
【解决方案3】:

以下是MDN docsObject.prototype 的看法:

所有对象都从 Object.prototype 继承方法和属性,尽管它们可能被覆盖(除了具有空原型的对象,即 Object.create(null))。

换句话说,Object.prototype几乎所有对象的根。 ObjectFunction 都是 Function.prototype 的子代,Function.prototype 本身就是 Object.prototype 的子代。

当我忽略构造函数并专注于原型链时,我发现 Javascript 中的继承更容易理解。对我来说,这样做会使问题和答案都变得更简单;像这样的问题:

  • 什么是对象的原型链?
  • 给定两个对象 x 和 y,x 在 y 的原型链中吗? (或者:y 是否继承自 x?)

您可以使用这个小 sn-p(有用的文档 here)轻松地自己研究原型链:

function getPrototypes(obj) {
    var protos = [],
        parent = obj;
    while ( true ) {
        parent = Object.getPrototypeOf(parent);
        if ( parent === null ) {
            break;
        }
        protos.push(parent);
    }
    return protos;
}

根据这个函数,primitives 没有原型:

> getPrototypes(3)
TypeError: Object.getPrototypeOf called on non-object

所以让我们把图元排除在外。 对于对象,层次结构看起来像这样(其中子级缩进到其父级的右侧)。据我所知,真正的多重继承在Javascript中是不可能的,所以每个对象都有一个父对象,除了Object.prototype,它没有父对象:

  • Object.create(null)
  • Object.prototype
    • arguments
    • Object.create(Object.prototype)
    • {}
      • Object.create({}) -- 假设 {} 是上一行的对象,而不是单独的新对象
    • JSON
    • 数学
    • Array.prototype
      • []
      • new Array()
    • Function.prototype
      • 数组
      • 对象
      • 功能
      • 号码
      • 布尔值
      • 字符串
      • 正则表达式
      • function MyFunction() {}
      • Object.keys
      • Object.prototype.toString
      • Object.prototype.toString.call
      • getPrototypes
    • MyFunction.prototype
      • new MyFunction()
    • String.prototype
      • new String('abc')
        • Object.create(new String('abc'))
    • Number.prototype
      • new Number(41)
    • Boolean.prototype
      • new Boolean()
      • new Object(false)
    • RegExp.prototype
      • /a/

这很混乱!请注意,在大多数情况下,X.prototype 不是X 的原型!如果我们有一些更好的术语,情况可能会有所改善;但是......我们不 :( 如您所见,NumberBoolean 等构造函数与它们生成的对象处于单独的子层次结构中。此外,Object 本身继承自 Function.prototype 继承来自Object.prototype

如果您尝试这些示例,您还会发现使用constructor 属性是检查对象原型的糟糕方法,原因有几个。鉴于var str1 = new String('abc'); var str2 = Object.create(str1);,原因如下:

  1. 一个对象可以是多个构造函数的实例:str1 instanceof Stringstr1 instanceof Object 都是 true。这未反映在 constructor 属性中:str1.contructor === String

  2. 有时,我们无法为对象原型链中的每个对象找到构造函数:Object.getPrototypeOf(str2).constructor === String。这是因为constructor 属性继承自String.prototypestr1.hasOwnProperty('constructor')str2.hasOwnProperty('constructor') 均为假,而Object.getPrototypeOf(str1).hasOwnProperty('constructor') 为真。幸运的是,您可以使用 Object.prototype.isPrototypeOf 方法来代替:str1.isPrototypeOf(str2) 是真的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-27
    • 2016-05-13
    • 2014-02-16
    • 2012-05-16
    • 2011-09-28
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    相关资源
    最近更新 更多