为什么`Object.prototype.toString`总是返回`[object *]`?

时间:2012-10-31 05:33:33

标签: javascript ecmascript-5

如果您致电Object.prototype.toString.call(anything),结果始终为[object Something],其中Something可能是其中之一。我的问题是为什么“对象”在那里?总是把它放在那里似乎是多余的。它没有告诉你关于传入的论点的任何信息。

Object.prototype.toString.call(null);
=> [object Null]

Object.prototype.toString.call(undefined);
=> [object Undefined]

由于nullundefined不是对象(并且CheckObjectCoercible失败),因此“对象”部分确实显得毫无意义。

我不得不认为最初有一些原因是“对象”部分放在那里,即使原因已经丢失了,现在它已经因历史原因而被保留了。

任何人都可以帮忙解释一下吗?


要清楚,我已经知道Object.prototype.toString如何用于获取对象的[[Class]](类型)。我的问题涉及返回字符串格式的原因 - 特别是开头的“对象”部分。我想知道这一部分是否有原因,或者这部分是否有可能的未来原因。也许在未来它可能会返回“对象”以外的东西?我能指望它总是返回“对象”吗?如果是这样,为什么它甚至返回呢?谁想要一个函数总是返回相同的东西,无论输入是什么?

3 个答案:

答案 0 :(得分:3)

Annex F of the ES5.1 specificationObject.prototype.toString

  

15.2.4.2:版本5处理undefined和null,因为此值导致现有代码失败。修改了规范以保持与此类代码的兼容性。新的步骤1和2添加到算法中。

这是在ES5.1规范中进行的更正。在ES5之前,将null或undefined传递给toString总是会导致传递全局对象。 ES5中与严格模式相关的更改会导致null和undefined无需修改即可传递。如ES5中所指定,将null或undefined传递给Object.prototype.toString会导致TypeError异常。这个例外打破了一些现有的代码,因此我们必须修改规范,以免在这种情况下抛出。

那么toString应该返回null和undefined?事实证明,许多现有代码还希望Object.prototype.toString始终返回"[object *]"形式的字符串。因此,我们决定使null和undefined生成"[object Null]""[object Undefined]"

这似乎已经奏效并且通常允许现有的基于ES3的代码在ES5 / 5.1中存在严格模式相关更改的情况下继续工作。

答案 1 :(得分:2)

好的,想到这样:

  1. JavaScript中的所有值实际上都是类的实例。甚至undefinednull在解释器中实现为单例对象。例如,undefined实际上是Rhino中的Undefined.instance(用Java实现)。
  2. 定义的toString方法公开JavaScript值的类名。但是,由于该值不是类本身而是类的实例,toString将返回[object ClassName]形式的字符串。
  3. 是的,[object *]表单是多余的。然而有人希望它像那样,所以我们坚持下去。现在它就在那里,如果突然发生变化,它会引起很多问题。依赖它的旧代码可能会破坏。
  4. 编辑:重要的是要注意JavaScript何时结束并且解释器开始。例如,当您在JavaScript中调用函数时,解释器会创建一个新的执行上下文,该上下文是编写JavaScript解释器的语言中的对象(而不是JavaScript本身)。

    类似地,JavaScript值的[[Class]]是编写JavaScript解释器的语言中的类,用于创建该类的实例。例如,在Rhino函数中是类org.mozilla.javascript.BaseFunction的实例。此类有一个名为getClassName的方法returns Function[[Class]]个实例的BaseFunction

    类似地,有一个名为org.mozilla.javascript.Undefined的类,它有一个名为instance的静态属性,它是Undefined的{​​{3}}。

答案 2 :(得分:1)

以下是ES5的说法:

  

15.2.4.2 Object.prototype.toString ( )

     

调用toString方法时,将执行以下步骤:

     
      
  1. 如果未定义此值,请返回“[object Undefined]”。
  2.   
  3. 如果此值为null,则返回“[object Null]”。
  4.   
  5. 设O是调用ToObject传递此值作为参数的结果。
  6.   
  7. 让class为O的[[Class]]内部属性的值。
  8.   
  9. 返回String值,该值是连接三个字符串“[object”,class和“]”的结果。
  10.   

因此toString首先处理undefinednull,然后将参数转换为对象,然后返回该对象的内部[[Class]]属性。请注意,toString旨在被对象所包含,因此它的行为就像它一样公平。

在ECMAScript中,一切都是对象。基元只是避免以下事情的便利:

// Create number objects with the same value
var a = new Number(7);
var b = new Number(7);

a == b; // false

a.valueOf() == b.valueOf(); // true

JavaScript的主要目标是简单。宽松的打字使生活更轻松,但这也意味着有一些缺点需要学习。