Прототипы в JavaScript

При поиске в Google документации или методов в JavaScript может появиться Array.prototype или Object.prototype, но что такое прототипы? Должны ли они быть сделаны? Чем хороши прототипы?

Прототипы — это объекты.

В JavaScript всякий раз, когда создается сложный тип данных (например, объект, массив или функция), на него ссылается родной объект-прототип JavaScript, который содержит свойства.

Свойства прототипа обычно представляют собой функции-конструкторы и различные методы, которые можно использовать с созданным типом данных (например, toString, filter, call, apply).

Тип данных может ничего не содержать, например литерал объекта ({}), но с помощью записи через точку вы можете получить доступ к конструктору литерала объекта, методу toString и другим свойствам прототипа.

Объекты, массивы и функции имеют свои собственные прототипы. И массивы, и функции имеют прототип родительского объекта, который называется цепочкой прототипов.

Одно из преимуществ возможности ссылаться на прототип или родительский прототип заключается в том, что создаваемый тип данных может ссылаться на методы без необходимости хранить какие-либо ссылки в памяти. Это может серьезно сократить длину кодирования и, таким образом, уменьшить количество ошибок кодирования.

Примеры кода в консоли

Вы можете попробовать это сами. В браузере откройте консоль (нажмите F12 или Cmd+Option+J на Mac). Теперь введите «let obj = {};» (литерал объекта) в консоли. Затем введите obj.constructor и нажмите Enter, затем введите obj.toString() и нажмите Enter. Обратите внимание, что у этого совершенно пустого объекта есть конструктор и метод toString, доступ к которому можно получить с помощью записи через точку. Если вы просто вызовете объект в консоли, вы увидите его нативный прототип.

let obj = {};
undefined
obj.constructor;
ƒ Object() { [native code] }
obj.toString();
“[object Object]”
obj;
{}
__proto__: Object

Теперь давайте посмотрим на литерал массива. Снова введите в консоль «let arr = [];» и нажмите ввод. Затем введите arr.constructor, нажмите Enter и arr.toString(), нажмите Enter. Опять же, этому пустому массиву, который вы только что создали, был предоставлен собственный прототип массива с конструктором массива и версией метода toString для массива.

let arr = [];
undefined
arr.constructor;
ƒ Array() { [native code] }
arr.toString();
“”

Далее давайте попробуем сделать то же самое с функцией. В консоли введите «let fn = () =› {};» (совершенно пустая функция ES6). Снова введите fn.constructor, нажмите Enter, fn.toString() и нажмите Enter. Как вы уже, наверное, догадались, эта совершенно пустая функция имеет конструктор Function и метод toString.

let fn = () => {};
undefined
fn.constructor;
ƒ Function() { [native code] }
fn.toString();
“() => {}”

Создание прототипов

Прототипы также можно создавать с помощью функций-конструкторов. В следующем примере мы будем использовать фрагмент кода, создающий конструктор Grub и Bee с использованием псевдоклассического создания экземпляров (не беспокойтесь о том, что такое псевдоклассическое создание экземпляров, игнорируйте сложность).

const Grub = function() {
  this.age = 0;
  this.color = “pink”;
  this.food = “jelly”;
};
Grub.prototype.eat = () => console.log(“buzz, munch, buzz”);

Здесь мы создаем функцию-конструктор Grub, которую будем использовать в качестве прототипа для нашего конструктора Bee.

const Bee = function() {
  this.age = 5;
  this.color = “yellow”;
  this.job = “keep on growing”
};
Bee.prototype = new Grub();
Bee.prototype.constructor = Bee;

Теперь давайте построим пчелу и проверим некоторые ее свойства.

let bee = new Bee();
undefined
bee.constructor;
ƒ () {
 this.age = 5;
 this.color = “yellow”; 
 this.job = “keep on growing”
}
bee.eat(); 
buzz, munch, buzz
undefined
bee.toString();
“[object Object]”

Вы можете видеть, что у нашей пчелы есть конструктор Bee, есть метод eat из прототипа Grub и все еще есть метод toString, унаследованный от родного прототипа Object. Для этого требуется менее 15 строк кода.

Вывод

В заключение, пожалуйста, помните, что прототипы — это объекты, содержащие методы, которые могут использоваться типом данных с использованием записи через точку. В JavaScript есть нативные прототипы для типов данных. Прототипы могут быть созданы и объединены в цепочку (дочерний-родительский) вместе.