Ответ 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() (для объектов)? для подобных обсуждений.