为什么有些数组方法依赖于全局数组对象?
我正在检查MDN docs on arrays,当我们想要测试一个对象是否为数组时,我们使用isArray()
。然而,它的用法与大多数其他方法非常不同。使用常规语法时,会弹出错误:
console.log([1,2,3].isArray()); // TypeError: [1, 2, 3].isArray is not a function
鉴于这确实起作用:
console.log(Array.isArray([1,2,3]))
我不明白为什么isArray()
(以及其他几个方法)依赖于某个全局对象,而不是仅仅通过所讨论的对象访问。为什么某些方法需要全局数组对象?
解决方案
而不仅仅是可以通过相关对象访问。
,因为Array.isArray
的全部目的是在未知对象上调用。您不知道它是否是数组,也不知道该方法在它上是否可访问。静态方法甚至可以与null
这样的值一起使用,当您尝试对它们调用方法时,这将不可避免地引发异常。
离题:
isArray
作为实例方法可调用可以工作。在Smalltalk、Ruby或Io等一切都是对象的语言中,甚至像nil
这样的东西也可以有isNil
方法。当然,这种方法还有其他问题,因为使用动态方法分派时,每个任意对象都可能覆盖该方法并声明为数组--另一方面,这正是我们希望duck typing。
我们甚至可以使用Object.prototype.isArray = () => false;
和Array.prototype.isArray = () => true;
在JS中模拟这一过程。除了在null
和undefined
上失败外,它仍然不能处理不是从(我们的领域)Object.prototype
继承的对象。而混合了数据字段和方法的JavaScript"属性"也没有帮助(考虑一下从JSON字符串{"isArray":"maybe"}
解析的对象)。我们总是必须预料到.isArray
不是函数,或者它被抛出的方法覆盖时会出现异常。
如果我们想要在JS中进行鸭子类型,检查对象是否具有整型.length
属性通常是可行的。或更高级,尝试遵循symbol-based iteration protocol。(例如,Array.from
就是这样使用的)。
但是由于数组在JS中有点特殊(凭借其神奇的.length
属性),我们需要一种内置的可靠方法来检测它们,这正是Array.isArray
所做的。
关于其他静态Array
方法:Array.of
非常明显,它是工厂函数(类似于构造函数),而不能是实例方法,因为首先没有实例可用。对于Array.from
,情况更像isArray
,鸭子类型Object.prototype.toArray
方法也同样有效,但由于实际和设计原因而被取消。
有关类似的讨论,请参阅Why were ES5 Object methods not added to Object.prototype?和Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?。
相关文章