首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解Array.isArray Polyfill

了解Array.isArray Polyfill
EN

Stack Overflow用户
提问于 2020-05-29 04:42:06
回答 2查看 683关注 0票数 3

我在MDN上执行Array.isArray方法的polyfill时,我发现了以下内容:

代码语言:javascript
复制
if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

虽然这是可行的,但我想知道为什么MDN没有列出以下内容作为isArray的polyfill

代码语言:javascript
复制
if (!Array.isArray) {
  Array.isArray = function(arg) {
    return arg.constructor === Array;
  };
}

上面的代码有点简短和简单。我想知道与上面的实现相比,使用MDN的实现有什么优势吗?

EN

回答 2

Stack Overflow用户

发布于 2020-05-29 06:18:44

使MDN polyfill成为可安全使用的polyfill的最重要原因是,数组是一个外来对象。区分外来物体的最好方法是通过使用与该物体相关的外来特征-也就是说,外来物体的外来属性。

如果查看Object.prototype.toString方法的规范,就会发现它使用了抽象操作isArray,该操作检查奇异的数组对象。

另一方面,看看constructor property的规范。它不是数组的奇特属性,所以javascript代码可以很容易地更改它。

代码语言:javascript
复制
const x = [];
x.constructor = Object

事实上,构造函数属性更多地用于元编程。您可以-在es5中-创建子类,而不需要接触构造函数属性。

现在,以下是您的实现中可能出现问题的地方:

代码语言:javascript
复制
const customIsArray = function(arg) {
    return arg.constructor === Array;
};

// 1) won't work with subclasses of Array

class CustomArray extends Array {
    // ...
}

const customArray = new CustomArray()
customIsArray(customArray) // false
Array.isArray(customArray) // true

// 2) won't work across different realms (iframes, web workers, service workers ... if we are speaking about the browser environment)

const iframe = document.createElement('iframe')
document.body.appendChild(iframe)
const IframeArray = iframe.contentWindow.Array;
const iframeArray = new IframeArray();
customIsArray(iframeArray) // false
Array.isArray(iframeArray) // true

// 3) won't work with few edge cases like (customIsArray will return true, while Array.isArray will return false)

const fakeArray1 = { __proto__: Array.prototype }
const fakeArray2 = { constructor: Array }

customIsArray(fakeArray1) // true
Array.isArray(fakeArray1) // false

customIsArray(fakeArray2) // true
Array.isArray(fakeArray2) // false 
票数 3
EN

Stack Overflow用户

发布于 2020-05-29 04:45:05

一个问题是,一个constructor属性为Array的非数组对象会在不应该传递的时候传递:

代码语言:javascript
复制
// Bad polyfill, do not use
Array.isArray = function(arg) {
  return arg.constructor === Array;
};

const badObj = {};
badObj.constructor = Array;
console.log(Array.isArray(badObj));

上面的情况非常奇怪,但polyfill必须尽可能符合规范,即使它需要更复杂的代码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62074163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档