javascript – 我可以在不使用Array构造函数或数组文字的情况下创建Array.isArray()返回true的对象吗?

通过将其原型设置为Array.prototype,我可以轻松地使普通对象看起来像一个数组:

const obj = {};
Reflect.setPrototypeOf(obj, Array.prototype);

(我知道魔术长度属性和稀疏数组也存在一些问题,但这不是这个问题的重点.)

我想让Array.isArray(obj)返回true(当然不修改Array.isArray()方法). MDN polyfill for Array.isArray()如下:

06001

通过使用Symbol.toStringTag属性,我可以使Object.prototype.toString.call(obj)返回'[object Array]’:

obj[Symbol.toStringTag] = 'Array';
console.log(Object.prototype.toString.call(obj) === '[object Array]'); // true

现在,polyfilled Array.isArray()为obj返回true(请忽略不支持Array.isArray()的浏览器都不支持Symbol.toStringTag的事实).但是,本机Array.isArray()函数仍然为obj返回false.我查看了ECMAScript 2017规范,它说Array.isArray()使用抽象操作IsArray,如果参数是Array异常对象,则返回true.如果参数是一个代理,它直接在目标对象上调用IsArray,所以似乎使用代理在这里没有帮助.

有没有办法让Array.isArray(obj)返回true?为了清楚起见,我不想修改Array.isArray()或任何其他内置对象.

这与Can you fake out Array.isArray() with a user-defined object?基本上是同一个问题,但5年前被问到,答案基于ECMAScript 5规范.我正在寻找基于ECMAScript 2017规范的答案.

最佳答案
不,正如您已经说过的一个真正的数组(这是Array.isArray检测到的)是一个数组异域对象,这意味着它的.length以一种特殊的方式运行.

构造它的唯一方法是使用数组构造函数或Array的子​​类(进而调用数组构造函数)或来自另一个领域的相同.还有无数其他方法返回新数组(例如String :: split,String :: match,Array.from,Array.of,Array原型方法,Object.keys,Object.getOwnPropertyNames).
此外,用于标记模板或代理应用/构造​​陷阱的函数将接收全新的数组,并且数组也构造为Promise.all或.entries()迭代器的结果的一部分.

如果您正在寻找创建数组的语法方法,那么数组文字将是您的主要选择,但是解构表达式(在数组文字或函数中)也可以从迭代器创建数组.

如果您的实际问题是“我可以将任意对象转换为数组奇异对象吗?”,答案就是公司编号.

转载注明原文:javascript – 我可以在不使用Array构造函数或数组文字的情况下创建Array.isArray()返回true的对象吗? - 代码日志