Прототипы в 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 есть нативные прототипы для типов данных. Прототипы могут быть созданы и объединены в цепочку (дочерний-родительский) вместе.