Skip to main content

Встроенные прототипы

  • Все встроенные объекты следуют одному шаблону:
    • Методы хранятся в прототипах (Array.prototype, Object.prototype, Date.prototype и т.д.).
    • Сами объекты хранят только данные (элементы массивов, свойства объектов, даты).
  • Примитивы также хранят свои методы в прототипах объектов-обёрток: Number.prototype, String.prototype, Boolean.prototype. Только у значений undefined и null нет объектов-обёрток.
  • Встроенные прототипы могут быть изменены или дополнены новыми методами. Но не рекомендуется менять их. Единственная допустимая причина – это добавление нового метода из стандарта, который ещё не поддерживается движком JavaScript.

Object.prototype

Краткая нотация obj = {} – это то же самое, что и obj = new Object(), где Object – встроенная функция-конструктор для объектов с собственным свойством prototype, которое ссылается на огромный объект с методом toString и другими.

let obj = {};
alert( obj ); // "[object Object]" ?

Таким образом, когда вызывается obj.toString(), метод берётся из Object.prototype.

Другие встроенные прототипы

Другие встроенные объекты, такие как Array, Date, Function и другие, также хранят свои методы в прототипах.

Примитивы

Самое сложное происходит со строками, числами и булевыми значениями.

Если мы попытаемся получить доступ к их свойствам, то тогда будет создан временный объект-обёртка с использованием встроенных конструкторов String, Number и Boolean, который предоставит методы и после этого исчезнет. Эти объекты создаются невидимо для нас, и большая часть движков оптимизирует этот процесс, но спецификация описывает это именно таким образом. Методы этих объектов также находятся в прототипах, доступных как String.prototype, Number.prototype и Boolean.prototype.

💥 Значения null и undefined не имеют объектов-обёрток

Изменение встроенных прототипов

Встроенные прототипы можно изменять. Например, если добавить метод к String.prototype, метод становится доступен для всех строк:

String.prototype.show = function() {
alert(this);
};
"BOOM!".show(); // BOOM!

💥 Важно: Прототипы глобальны, поэтому очень легко могут возникнуть конфликты. Если две библиотеки добавляют метод String.prototype.show, то одна из них перепишет метод другой.

Изменение встроенных прототипов считается плохой идеей. *** В современном программировании есть только один случай, в котором одобряется изменение встроенных прототипов. Это создание полифилов.***

Заимствование у прототипов

Некоторые методы встроенных прототипов часто одалживают.

Например, если мы создаём объект, похожий на массив (псевдомассив), мы можем скопировать некоторые методы из Array в этот объект.

let obj = {
0: "Hello",
1: "world!",
length: 2,
};
obj.join = Array.prototype.join;
alert( obj.join(',') ); // Hello,world!

Это работает, потому что для внутреннего алгоритма встроенного метода join важны только корректность индексов и свойство length, он не проверяет, является ли объект на самом деле массивом. И многие встроенные методы работают так же.

Альтернативная возможность – мы можем унаследовать от массива, установив obj.__proto__ как Array.prototype, таким образом все методы Array станут автоматически доступны в obj.

Но это будет невозможно, если obj уже наследует от другого объекта. Помните, мы можем наследовать только от одного объекта одновременно.

Заимствование методов – гибкий способ, позволяющий смешивать функциональность разных объектов по необходимости.

🚀 Источник: https://learn.javascript.ru/native-prototypes