我可以通过将其原型设置为轻松使普通对象看起来像数组Array.prototype
:
const obj = {};
Reflect.setPrototypeOf(obj, Array.prototype);
(我知道魔法也存在一些问题length
属性和稀疏数组,但这不是这个问题的重点。)
我要实现Array.isArray(obj)
return true
(当然不修改Array.isArray()
方法)。这MDN Polyfill 用于Array.isArray()如下:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
通过使用Symbol.toStringTag我可以创造的财产Object.prototype.toString.call(obj)
return '[object Array]'
:
obj[Symbol.toStringTag] = 'Array';
console.log(Object.prototype.toString.call(obj) === '[object Array]'); // true
现在聚填充Array.isArray()
回报true
for obj
(请忽略以下事实:没有一个浏览器不支持Array.isArray()
确实支持Symbol.toStringTag
)。然而,本土Array.isArray()
函数仍然返回false
for obj
。我查看了 ECMAScript 2017 规范,它说Array.isArray()使用抽象操作IsArray,返回true
如果参数是一个 Array 奇异对象。如果参数是代理,它会调用IsArray
直接在目标对象上,因此似乎使用代理在这里没有帮助。
有什么办法可以使Array.isArray(obj)
return true
?明确地说,我不想修改Array.isArray()
或任何其他内置对象。
这基本上是同一个问题你能用用户定义的对象伪造 Array.isArray() 吗?,但这是 5 年前提出的问题,答案是基于 ECMAScript 5 规范。我正在寻找基于 ECMAScript 2017 规范的答案。