为什么有些数组方法依赖于全局Array对象?

cha*_*ham 10 javascript arrays prototype

我正在浏览数组上MDN文档,当我们想要测试一个对象是否是我们使用的数组时isArray().但是,它的使用与大多数其他方法非常不同.使用常规语法时会弹出一个错误:

console.log([1,2,3].isArray());  // TypeError: [1, 2, 3].isArray is not a function
Run Code Online (Sandbox Code Playgroud)

虽然这确实有效:

console.log(Array.isArray([1,2,3]))
Run Code Online (Sandbox Code Playgroud)

我不明白为什么isArray()(以及其他一些方法)依赖于某些全局对象而不是仅通过所讨论的对象可访问.为什么有些方法需要全局数组对象?

Ber*_*rgi 16

而不仅仅是通过有问题的对象访问.

因为整个目的Array.isArray是要调用未知对象.你不知道它是否是一个数组,你不知道该方法是否可以访问它.静态方法甚至可以使用类似的值null,当您尝试在它们上调用方法时,这将不可避免地引发异常.


题外话:

isArray作为实例方法调用可以工作.在所有东西都是对象的语言中,比如Smalltalk,Ruby或Io,即使是类似的东西nil也可以有isNil方法.这种方法当然还有其他问题,因为动态方法调度每个任意对象都可以覆盖该方法并声称是一个数组 - 另一方面,这正是我们想要的鸭子类型.

我们甚至可以在JS中使用Object.prototype.isArray = () => false;和模拟这个Array.prototype.isArray = () => true;.除了没有按规定nullundefined,它仍然不会与不从(我们的境界的)继承对象的工作Object.prototype.混合数据字段和方法的JavaScript"属性"也没有帮助(考虑从JSON字符串解析的对象{"isArray":"maybe"}).我们总是不得不期待一个异常,既不.isArray是一个函数,也不会被一个抛出的方法覆盖.
如果我们想在JS中输入duck,那么检查一个对象是否具有整数.length属性通常是要走的路.或者更高级,尝试遵循基于符号的迭代协议.(这就是Array.from使用的东西).


但是由于数组在JS(它们具有魔力.length属性)方面有点特殊,我们需要一种内置的可靠方法来检测它们,这就是Array.isArray它的作用.

关于其他静态Array方法:Array.of非常明显,它是一个工厂函数(如构造函数),它不能是实例方法,因为首先没有实例可以使用.对于Array.from这种情况有点像isArray,鸭子打字的Object.prototype.toArray方法可能也有效,但由于实际和设计原因被解雇.

另请参见为什么ES5对象方法未添加到Object.prototype?为什么Object.defineProperty(),而不是this.defineProperty()(的对象)?进行类似的讨论.

  • @PatrickRoberts那么一个人不能低估评论呢?(虽然我没看到它有什么问题) (3认同)
  • 你的回答比你的评论更有意义 (2认同)
  • 我认为这个评论对记录非常有意义 (2认同)