【问题标题】:Why the Array.isArray algorithm is ES5 performs a type check?为什么 Array.isArray 算法是 ES5 进行类型检查的?
【发布时间】:2016-07-02 15:03:50
【问题描述】:

在 SO 和 google 中发现的每个关于检查对象是否为数组的问题最有可能最终得到此解决方案

function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]'
}

所有其他替代方案都有误报或不完全支持。

来源:

http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

How to detect if a variable is an array

当我阅读 15.4.3.2 部分中的 ES5 规范时,发现函数 Array.isArray 的描述算法在 IE9+、Chrome 5+、Firefox 4+、Opera 10.5+ 和 Safari 5+ 中执行相同的检查,但是这个算法有两个额外的步骤。

function isArray(obj) {
    if (typeof obj !== 'object') {
        return false;
    }
    // Here they check only against the [[Class]] part 
    // and of course they don't have to use the ugly Object.prototype.toString.call
    // but this is pretty much the same comparison
    if (Object.prototype.toString.call(obj) === '[object Array]') {
        return true;
    }
    return false;
}

现在我的问题是他们为什么要先检查类型?对于仍然具有 [[Array]] 内部类的对象,是否有特殊情况会返回 false?

【问题讨论】:

  • 请注意,这些东西基本上已经过时了,ES2015 根本不使用[[Class]]es。
  • @georg 我知道你的意思,但是直到所有浏览器都完全支持ES2015 并且世界上只有最少数量的浏览器不支持(可能需要十年)学习这是并非完全没用,因为这是我们今天仍在使用的语言,即使我们使用了转译器。
  • 只是说,Array.isArray 完全支持所有严肃的浏览器。
  • @Bergi 是的,我知道这是真的。请注意,当我说“直到所有浏览器完全支持 ES2015”时,我指的是 [[Class]] 内部属性,而不是缺少 Array.isArray 方法。我已经看到有些人带着像Array.isArray ? Array.isArray(obj) : Object.prototype.... 这样的 pollyfill 来确定。难以置信,我见过一些环境仍然使用 IE8 o_O。

标签: javascript arrays algorithm types ecmascript-5


【解决方案1】:

让我们看看算法:

  1. 如果 Type(arg) 不是 Object,则返回 false。
  2. 如果 arg 的 [[Class]] 内部属性的值为“Array”,则返回 true。
  3. 返回 false。

该算法包含此检查,因为不是对象的值没有internal properties。但由于算法访问值的内部属性[[Class]],它必须断言该值是一个对象。

这个检查对于 polyfill 来说确实是不必要的,因为它们不访问值的任何属性。但是,它确实使 polyfill 更接近规范。

【讨论】:

  • 我读到有人在做return typeof (obj) === 'object' && Object.prototype…,我想“好吧,这一定是错的”,但我不知道为什么。谢谢!!
  • 要记住的一点是typeof 不等同于规范的Type 函数。 typeof nulltypeof function() {} 的结果与 Type(null)Type(function() {}) 不同。
  • 不是对象的值的情况是NullUndefined或者它们还包括StringBooleanNumber
  • Null、Undefined、String、Number、Boolean 和 Symbol (ES6) 都是原始类型。但是,String、Number 和 Boolean 也有 Object 等价物,例如es5.github.io/#x4.3.18"foo" 是原始字符串,new String("foo") 是字符串对象。它们是不同的类型(字符串与对象)。
  • 是的,这就是为什么Object.prototype.toString 算法没有将这些视为“特殊情况”,因为它们将在第 3 步调用ToObject 时进行转换,将它们转换为它们的 Object 等价物,但Null 和 Undefined 将抛出 TypeError 因此需要特殊处理。谢谢!!
猜你喜欢
  • 1970-01-01
  • 2015-04-14
  • 2014-11-10
  • 2019-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多