javascript是否存储超出原型的数据类型信息?

问题描述

我正在研究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,不包含所需的“数组”字符串。

解决方法

在任何对象上调用.toString()时,它都会创建格式为[object x]的字符串,其中x是内置构造函数(例如{{ 1}}和Date

调用Array时,需要执行几个步骤,其中一个步骤是检查.toString()中的this的值是否为数组。如果是数组,则将tag设置为字符串.toString()

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

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

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