为什么 Intl 和 Reflect 的默认字符串表示形式是`[object Object]`?

Ben*_*Ben 2 javascript

内置“命名空间”对象的字符串标签如MathJSON是同名的。

但是,这不是为案件IntlReflect。为什么?

console.log(Object.prototype.toString.call(Math))    // [object Math]
console.log(Object.prototype.toString.call(JSON))    // [object JSON]
console.log(Object.prototype.toString.call(Atomics)) // [object Atomics]

// ...but

console.log(Object.prototype.toString.call(Intl))    // [object Object] (?!)
console.log(Object.prototype.toString.call(Reflect)) // [object Object] (?!)
Run Code Online (Sandbox Code Playgroud)

Cer*_*nce 6

因为这就是规范所要求的。

ECMAScript 规范说Math对象应该有一个[Symbol.toStringTag]Math hereAtomicsJSON也是如此。

但是,对于Intl 对象Reflect对象没有这样的要求。(嗯,对 Reflect没有这样的要求,但在 2020 年 7 月发生了变化)

对于Reflectand Intlallenwb 说没有添加标签是因为:

在 ES5 之前,ES 中唯一类似命名空间的对象是 Math 对象。由于可能已被历史遗忘的原因,它被指定为 [[Class]] 内部内部属性,其值为“Math”。在所有其他方面,它就是我们现在所说的普通对象。

ES5 添加了 JSON 对象作为命名空间对象,我们只是遵循 Math 建立的模式。

ECMA-402 第 1 版引入 Intl 对象作为名称空间对象。它只是一个普通对象,并没有指定具有 [[Class]] 内部属性。因此,它将 OptoString 视为“[object Object]”。

ES6 消除了 [[Class]] ,因为它被广泛滥用,结合 Object.prototype.toString 执行(通常是不必要的或不受欢迎的)伪名义类型检查。相反,我们通过 @@toStringTag 属性使 OptoString 可扩展。为了向后兼容,我们更改了 OptoString,这样所有来自 ES5 的真正奇特的对象都可以在 toString 中检测到,从而保留了它们的旧 toString 值。这使得 Math 和 JSON(在 ES6 中只是普通对象)成为唯一具有特殊遗留 OptoString 行为的遗留普通对象。我们使用@@toStringTag 机制使它们的 OptoString 行为向后兼容。

对于新的 ES6 内置“类”(Promise、Map、Set、Float32Array 等),我们在其原型对象上提供了 @@toStringTag 方法,以便 OptoString 可以识别这些类的实例。

Reflect 不是“类”,它只是使用普通对象定义的命名空间。此类命名空间对象现在广泛用于 JS 代码中,并且通常没有自定义的 toString 行为。所以我们遵循了ECMA-402 Intl的先例,没有给Reflect自己的@@toStringTag

部分动机是在 ES6 期间我们应该尽量减少内置函数的特殊性。总的来说,我们希望内建函数尽可能只是普通的对象,这些对象可能会被日常 JS 程序员实现,因此内建函数通常应该遵循我们期望普通 JS 程序员遵循的相同约定。对于类类构建,我们建立了在原型上使用 @@tostring 来命名类实例的新约定。希望这是一个能够流行于 JS 程序员的约定。对于像 Reflect 这样的命名空间对象,我们希望 JS 程序员继续使用直接对象实例(通常通过对象字面量构造),并且他们通常不会为它们提供唯一的 @@toStringTag 属性。因此,包括 Intl 和 Reflect 在内的大多数名称空间将打印为“[object Object]”。

TC39 提出了一个问题,关于将toStringTags添加到新命名空间如何有意义并使事情更加一致。因此,Reflect 现在有了这样一个标签,2020 年末的浏览器将开始支持它。Chrome从 86 开始支持它:

console.log(Reflect[Symbol.toStringTag]);
Run Code Online (Sandbox Code Playgroud)