Читаем Выразительный JavaScript полностью

// → А чёрный кролик говорит 'Всем капец...'

Важно отметить разницу между тем, как прототип связан с конструктором (через свойство prototype) и тем, как у объектов есть прототип (который можно получить через Object.getPrototypeOf). На самом деле прототип конструктора – Function.prototype, поскольку конструкторы – это функции. Его свойство prototype будет прототипом экземпляров, созданных им, но не его прототипом.

<p>Перегрузка унаследованных свойств</p>

Когда вы добавляете свойство объекту, есть оно в прототипе или нет, оно добавляется непосредственно к самому объекту. Теперь это его свойство. Если в прототипе есть одноимённое свойство, оно больше не влияет на объект. Сам прототип не меняется.

Rabbit.prototype.teeth = "мелкие";

console.log(killerRabbit.teeth);

// → мелкие

killerRabbit.teeth = "длинные, острые и окровавленные";

console.log(killerRabbit.teeth);

// → длинные, острые и окровавленные

console.log(blackRabbit.teeth);

// → мелкие

console.log(Rabbit.prototype.teeth);

// → мелкие

На диаграмме нарисована ситуация после прогона кода. Прототипы Rabbit и Object находятся за killerRabbit на манер фона, и у них можно запрашивать свойства, которых нет у самого объекта.

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

Та же перегрузка используется, чтобы дать стандартным функциям и массивам свои методы toString, отличные от метода базового объекта.

console.log(Array.prototype.toString == Object.prototype.toString);

// → false

console.log([1, 2].toString());

// → 1,2

Вызов toString массива выводит результат, похожий на .join(",") – получается список, разделённый запятыми. Вызов Object.prototype.toString напрямую для массива приводит к другому результату. Эта функция не знает ничего о массивах:

console.log(Object.prototype.toString.call([1, 2]));

// → [object Array]

<p>Нежелательное взаимодействие прототипов</p>

Прототип помогает в любое время добавлять новые свойства и методы всем объектам, которые основаны на нём. К примеру, нашим кроликам может понадобиться танец.

Rabbit.prototype.dance = function() {

  console.log("А " + this.type + " кролик танцует джигу.");

};

killerRabbit.dance();

// → А убийственный кролик танцует джигу.

Это удобно. Но в некоторых случаях это приводит к проблемам. В предыдущих главах мы использовали объект как способ связать значения с именами – мы создавали свойства для этих имён, и давали им соответствующие значения. Вот пример из 4-й главы:

var map = {};

function storePhi(event, phi) {

  map[event] = phi;

}

storePhi("пицца", 0.069);

storePhi("тронул дерево", -0.081);

Мы можем перебрать все значения фи в объекте через цикл for/in, и проверить наличие в нём имени через оператор in. К сожалению, нам мешается прототип объекта.

Object.prototype.nonsense = "ку";

for (var name in map)

  console.log(name);

// → пицца

// → тронул дерево

// → nonsense

console.log("nonsense" in map);

// → true

console.log("toString" in map);

// → true

// Удалить проблемное свойство

delete Object.prototype.nonsense;

Это же неправильно. Нет события под названием “nonsense”. И тем более нет события под названием “toString”.

Занятно, что toString не вылезло в цикле for/in, хотя оператор in возвращает true на его счёт. Это потому, что JavaScript различает счётные и несчётные свойства.

Все свойства, которые мы создаём, назначая им значение – счётные. Все стандартные свойства в Object.prototype – несчётные, поэтому они не вылезают в циклах for/in.

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

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных