Почему некоторые методы массива полагаются на глобальный объект Array?
Ответ 1
вместо того, чтобы быть доступным через данный объект.
Потому что цель Array.isArray
должна быть вызвана на неизвестные объекты. Вы не знаете, будет ли это массив, вы бы не знали, доступен ли на нем метод. Статический метод работает даже со значениями, такими как null
, что неизбежно вызовет исключение, когда вы попытаетесь вызвать метод на них.
Отступление:
isArray
, вызываемый как метод экземпляра, может работать. В языках, где все является объектом, например Smalltalk, Ruby или Io, даже такие вещи, как nil
, могут иметь метод isNil
. Конечно, этот подход имеет и другие проблемы, так как при динамическом отправке метода каждый произвольный объект может перезаписать метод и утверждать, что он является массивом - с другой стороны, именно то, что мы хотим для duck typing.
Мы могли бы даже имитировать это в JS, используя Object.prototype.isArray = () => false;
и Array.prototype.isArray = () => true;
. Помимо сбоев на null
и undefined
, он все равно не будет работать с объектами, которые не наследуются от (нашего царства) Object.prototype
. И JavaScript "свойства", которые смешивают поля данных и методы, также не помогают (рассмотрим объект, который разбирается из строки JSON {"isArray":"maybe"}
). Мы всегда должны ожидать, что исключение из .isArray
не является функцией, или из нее будет перезаписан метод, который вызывает.
Если мы хотим пойти на печать утки в JS, проверяя, является ли объект целочисленным свойством .length
, как правило, путь. Или более продвинутый, пытаясь следовать протокол итерации на основе символов. (То, что использует Array.from
, например).
Но так как массивы немного особенны в JS (с их магическим свойством .length
), нам нужен встроенный надежный способ их обнаружения и что делает Array.isArray
.
Что касается других статических методов Array
: Array.of
довольно очевиден, это функция factory (например, конструктор), и она не может быть методом экземпляра, потому что нет экземпляра для работы в первую очередь, Для Array.from
ситуация немного больше похожа на isArray
, подход с утиной печатью Object.prototype.toArray
мог бы сработать, но был отклонен по практическим соображениям и причинам дизайна.
См. также Почему методы класса ES5 не добавлены в Object.prototype? и Почему это Object.defineProperty() а не this.defineProperty() (для объектов)? для подобных обсуждений.
Ответ 2
.isArray() является статическим методом, он существует в классе "Array", но не в каждом конкретном экземпляре. Статические методы называются так: Array.isArray(). Object.create() - еще один пример.
Методы типа .map
или .slice
не являются статическими, поэтому они существуют в каждом экземпляре класса Array.
Ответ 3
Array
(обозначается символом "A" ) указывает объект native Array
. [...]
представляет собой экземпляр массива. Как и во многих языках, некоторые свойства/методы являются статическими. То есть, они не существуют в экземплярах только типа. Это часто делается, когда значение свойства или поведения метода не меняется от экземпляра к экземпляру, поэтому нет необходимости, чтобы он был "специфичным для экземпляра". Выяснение, если что-то является массивом, не изменяется от экземпляра к экземпляру (и, откровенно говоря, не имеет большого смысла задавать экземпляр массива, если он является экземпляром массива).