【问题标题】:Does javascript store datatype information beyond the prototype?javascript 是否在原型之外存储数据类型信息?
【发布时间】:2020-12-14 21:31:16
【问题描述】:

我正在研究 Javascript 中的原型设计,并且在一个实验中试图尽可能地去除一些基本对象的信息。但是,我在以下代码段中遇到了问题:

let x = [];
Object.setPrototypeOf(x, null);
console.log(Object.prototype.toString.call(x));
>>> [object Array]

我的困惑是:去掉原型后,Object.prototype.toString 怎么还知道xArray 类型?如果不是任何属性,这些信息来自哪里?运行Object.getOwnPropertyNames(x)Object.getOwnPropertySymbols(x),我看不到x 上的任何属性,其中包含字符串Array 的任何路径。这些信息存储在哪里?

如果这是那些“内部插槽”之一(虽然我不确定它会是哪个),有没有办法修改它?我至少可以直接访问它吗?

更新: Yousaf 注意到属性String.toStringTag 通常由Object.prototype.toString 访问,以提供代替上述示例中的“Array”的字符串。实际上,设置x[Symbol.toStringTag] = 'my_string' 允许我们更改.toString() 的值。但是,我认为它仍然没有解开谜团,因为x[Symbol.toStringTag]在我们设置它之前是undefined,不包含所需的“Array”字符串。

【问题讨论】:

  • 是的,JS 是通过它们的内部槽或作为一个外来对象(例如数组、函数等 - 它们具有与其属性或原型无关的特殊行为)来区分某些对象类型。您无法修改或访问这些内容。

标签: javascript types prototype prototype-programming


【解决方案1】:

当在任何对象上调用.toString() 时,它会创建一个[object x] 形式的字符串,其中x 是在DateArray 等内置构造函数的情况下的构造函数的名称。

当调用.toString() 时,会执行几个步骤,其中一个步骤是检查.toString() 内的this 的值是否是一个数组。如果它是一个数组,则标记设置为字符串'Array'

来自Spec - 19.1.3.6 Object.prototype.toString ( )

  1. 如果 isArray 为 true,则让 builtinTag 为“Array”。

在 ES6 之前,当在用户定义的构造函数的实例上调用 .toString() 时,会记录 [object Object]。 ES6 提供了一种使用众所周知的符号 Symbol.toStringTag 覆盖标签的方法。

【讨论】:

  • 嗯,我们不应该在这种情况下定义x[Symbol.toStringTag] 吗?好像是undefined
  • 参考toString()的内部工作,查看更新后的答案。
  • 这回答了我的问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 2016-02-19
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多