if (this.firstName && this.lastName) {
return this.firstName[0] + this.lastName[0];
}
}
};
Ключевое слово this ссылается на объект, к которому привязан наш метод getName. В данном случае объектом является spaceGuy, так как именно его мы используем в качестве точки входа в этот совершенный процесс навигации между прототипами (рис. 18.7).
Рис. 18.7. Ключевое слово this ссылается на spaceGuy!
Когда происходит вычисление метода getName и свойства firstName и lastName должны разрешиться, поиск начинается там, куда указывает ключевое слово this. Это означает, что наш поиск начинается с объекта spaceGuy, который, как выясняется, содержит свойства firstName и lastName. Именно поэтому мы получаем верный результат при вызове кода для getName (а также и getInitials).
Понимание, на что ссылается ключевое слово this, скрыто под галлонами пролитых чернил, и полноценное рассмотрение этого вопроса выходит далеко за рамки того, о чем мы собираемся говорить. Но хорошо то, что пройденного материала вам уже будет достаточно, чтобы решать большинство задач.
КОРОТКО О ГЛАВНОМ
Из-за неразберихи вокруг объектной ориентированности в JavaScript разумным было сделать рассмотрение этой темы глубоким и обширным, как мы и поступили. Многое из того, что было затронуто здесь, прямо или косвенно связано с наследованием — когда объекты разветвляются и основываются на других объектах. В отличие от классических языков, использующих классы как шаблоны для объектов, в JavaScript понятия классов, строго говоря, не существует. Здесь используется так называемая модель наследования прототипов. Вы не инстанцируете объекты из шаблона. Вместо этого вы создаете их либо заново, либо, чаще всего, копированием или клонированием другого объекта. JavaScript попадает в ту самую серую область, где не соответствует классической форме языка, но при этом имеет подобные классам конструкции (некоторые из них вы увидите позже), которые позволяют ему сидеть за одним столом с классическими языками. Не хочу здесь увлекаться навешиванием ярлыков.
Среди всего этого множества страниц я постарался сгруппировать новую функциональность JavaScript для работы с объектами и их расширения для ваших дальнейших нужд. Тем не менее еще многое предстоит рассмотреть, поэтому сделайте перерыв, и мы в ближайшем будущем затронем более интересные темы, которые дополнят пройденное более мощными и выразительными возможностями.
Дополнительные ресурсы и примеры:
• Понимание прототипов в JS: http://bit.ly/kirupaJSPrototypes
• Простое английское руководство по прототипам JS: http://bit.ly/kirupaPrototypesGuide
• Как работает prototype? http://bit.ly/kirupaPrototypeWork
• Это большая и странная тема, поэтому обращайтесь на форум https://forum.kirupa.com, если столкнетесь с какими-либо сложностями.
Глава 19. Расширение встроенных объектов
Как нам уже хорошо известно, JavaScript поставляется с богатым арсеналом встроенных объектов. Эти объекты обеспечивают некоторую базовую функциональность для работы с текстом, числами, коллекциями данных, датами и многим другим. Однако по мере углубления в этот язык, когда вы уже начинаете реализовывать более интересные и продуманные вещи, возникает желание выйти за рамки возможностей встроенных объектов.
Давайте взглянем на пример, демонстрирующий подобную ситуацию. В нем показано, как мы можем перемешивать содержимое массива:
function shuffle(input) {
for (let i = input.length — 1; i >= 0; i-) {
let randomIndex = Math.floor(Math.random() * (i + 1));
let itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
return input;
}
Мы используем функцию shuffle, просто вызвав ее и передав массив, чье содержимое нужно перемешать:
let shuffleArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
shuffle(shuffleArray);
// и результат…
console.log(shuffleArray);
После выполнения этого кода конечным результатом будет перегруппировка содержимого. Такая функциональность весьма полезна. Я бы даже сказал, что слишком полезна. Возможность производить перемешивание должна быть частью объекта Array и являться легко доступной наряду с такими его методами, как push, pop, slice и др.
Если бы функция shuffle была частью объекта array, то мы могли бы с легкостью использовать ее следующим образом:
let shuffleArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
shuffleArray.shuffle();
В этом примере мы расширяем встроенный объект (Array) заданной нами функциональностью (shuffle). В нескольких последующих разделах мы конкретно рассмотрим, как это делается, как работает и почему расширение встроенных объектов является спорным решением.