Why do some array methods rely on the global Array object?

烈酒焚心 提交于 2021-02-16 06:16:47

问题


I'm going through the MDN docs on arrays and when we want to test whether or not an object is an array we use isArray(). However, it's usage is very different to most of the other methods. When you use the regular syntax an error pops up:

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

Whereas this does work:

console.log(Array.isArray([1,2,3]))

I don't understand why isArray() (and a couple of other methods) rely upon some global object rather than just being accessible via the object in question. Why do some methods require the global array object?


回答1:


rather than just being accessible via the object in question.

Because the whole purpose of Array.isArray is to be called on unknown objects. You don't know whether it's an array, you wouldn't know whether the method was accessible on it. The static method even works with values like null, which would inevitably throw an exception when you tried to invoke a method on them.


Digression:

isArray being callable as an instance method can work. In languages where everything is an object, like Smalltalk, Ruby or Io, even things like nil can have a isNil method. This approach has other problems of course, as with dynamic method dispatch every arbitrary object could overwrite the method and claim to be an array - on the other hand, that's exactly what we want for duck typing.

We could even simulate this in JS using Object.prototype.isArray = () => false; and Array.prototype.isArray = () => true;. Apart from failing on null and undefined, it still wouldn't work with objects that don't inherit from (our realm's) Object.prototype. And JavaScript "properties" that mix data fields and methods don't help either (consider the object parsed from the JSON string {"isArray":"maybe"}). We would always have to expect an exception from either .isArray not being a function, or from it being overwritten with a method that throws.
If we want to go for duck typing in JS, checking whether an object has an integer .length property is usually the way to go. Or more advanced, trying to follow the symbol-based iteration protocol. (That's what Array.from uses, for example).


But since arrays are a bit special in JS (with their magic .length property), we want a built-in reliable way to detect them, and that's what Array.isArray does.

Regarding other static Array methods: Array.of is pretty obvious, it's a factory function (like a constructor) and it can't be an instance method because there is no instance to work with in the first place. For Array.from the situation is a bit more like with isArray, a duck-typing Object.prototype.toArray approach could have worked as well but was dismissed for practical and design reasons.

See also Why were ES5 Object methods not added to Object.prototype? and Why is it Object.defineProperty() rather than this.defineProperty() (for objects)? for similar discussions.




回答2:


.isArray() is a static method, it exists on the Array "class" but not on each particular instance. Static methods are called like this: Array.isArray(). Object.create() is another example.

Methods like .map or .slice are not static, so they exist on each instance of the Array "class".




回答3:


Array (denoted with a captial "A") indicates the JavaScript native Array object. [...] represents an instance of an array. As with many languages, some properties/methods are static. That is, they don't exist on instances only the type. This is often done when the value of the property or behavior of the method doesn't vary from instance to instance, so there's no need for it to be "instance-specific". Figuring out if something is an array, doesn't change from instance to instance (and frankly, doesn't make a lot of sense to ask an array instance if it is an instance of an Array).



来源:https://stackoverflow.com/questions/48957329/why-do-some-array-methods-rely-on-the-global-array-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!