
- •Введение
- •Введение в JavaScript
- •Справочники и спецификации
- •Редакторы для кода
- •Консоль разработчика
- •Основы JavaScript
- •Привет, мир!
- •Внешние скрипты, порядок исполнения
- •Структура кода
- •Современный стандарт, «use strict»
- •Переменные
- •Правильный выбор имени переменной
- •Шесть типов данных, typeof
- •Основные операторы
- •Операторы сравнения и логические значения
- •Побитовые операторы
- •Взаимодействие с пользователем: alert, prompt, confirm
- •Условные операторы: if, '?'
- •Логические операторы
- •Преобразование типов для примитивов
- •Циклы while, for
- •Конструкция switch
- •Функции
- •Функциональные выражения
- •Именованные функциональные выражения
- •Всё вместе: особенности JavaScript
- •Качество кода
- •Отладка в браузере Chrome
- •Советы по стилю кода
- •Как писать неподдерживаемый код?
- •Автоматические тесты при помощи chai и mocha
- •Структуры данных
- •Введение в методы и свойства
- •Числа
- •Строки
- •Объекты как ассоциативные массивы
- •Объекты: перебор свойств
- •Объекты: передача по ссылке
- •Массивы c числовыми индексами
- •Массивы: методы
- •Массив: перебирающие методы
- •Псевдомассив аргументов «arguments»
- •Дата и Время
- •Замыкания, область видимости
- •Глобальный объект
- •Замыкания, функции изнутри
- •[[Scope]] для new Function
- •Локальные переменные для объекта
- •Модули через замыкания
- •Управление памятью в JavaScript
- •Устаревшая конструкция «with»
- •Методы объектов и контекст вызова
- •Методы объектов, this
- •Преобразование объектов: toString и valueOf
- •Создание объектов через «new»
- •Дескрипторы, геттеры и сеттеры свойств
- •Статические и фабричные методы
- •Явное указание this: «call», «apply»
- •Привязка контекста и карринг: «bind»
- •Функции-обёртки, декораторы
- •Некоторые другие возможности
- •Типы данных: [[Class]], instanceof и утки
- •Формат JSON, метод toJSON
- •setTimeout и setInterval
- •Запуск кода из строки: eval
- •Перехват ошибок, «try..catch»
- •ООП в функциональном стиле
- •Введение
- •Внутренний и внешний интерфейс
- •Геттеры и сеттеры
- •Функциональное наследование
- •ООП в прототипном стиле
- •Прототип объекта
- •Свойство F.prototype и создание объектов через new
- •Встроенные «классы» в JavaScript
- •Свои классы на прототипах
- •Наследование классов в JavaScript
- •Проверка класса: «instanceof»
- •Свои ошибки, наследование от Error

Например:
truncate("Вот, что мне хотелось бы сказать на эту тему:", 20) = "Вот, что мне хоте..."
truncate("Всем привет!", 20) = "Всем привет!"
Эта функция имеет применение в жизни. Она используется, чтобы усекать слишком длинные темы сообщений.
Открыть песочницу с тестами для задачи.
К решению
Выделить число
важность: 4
Есть стоимость в виде строки: "$120". То есть, первым идёт знак валюты, а затем — число.
Создайте функцию extractCurrencyValue(str), которая будет из такой строки выделять числозначение, в данном случае 120.
Открыть песочницу с тестами для задачи.
К решению
Объекты как ассоциативные массивы
Объекты в JavaScript сочетают в себе два важных функционала.
Первый — это ассоциативный массив: структура, пригодная для хранения любых данных. В этой главе мы рассмотрим использование объектов именно как массивов.
Второй — языковые возможности для объектно-ориентированного программирования. Эти возможности мы изучим в последующих разделах учебника.
Ассоциативные массивы
Ассоциативный массив — структура данных, в которой можно хранить любые данные в формате ключ-значение.
Её можно легко представить как шкаф с подписанными ящиками. Все данные хранятся в ящичках. По имени можно легко найти ящик и взять то значение, которое в нём лежит.

В отличие от реальных шкафов, в ассоциативный массив можно в любой момент добавить новые именованные «ящики» или удалить существующие. Далее мы увидим примеры, как это делается.
Кстати, в других языках программирования такую структуру данных также называют «словарь» и «хэш».
Создание объектов
Пустой объект («пустой шкаф») может быть создан одним из двух синтаксисов:
1. o = new Object();
2. o = {}; // пустые фигурные скобки
Обычно все пользуются синтаксисом (2), т.к. он короче.
Операции с объектом
Объект может содержать в себе любые значения, которые называются свойствами объекта. Доступ к свойствам осуществляется по имени свойства (иногда говорят «по ключу»).
Например, создадим объект personдля хранения информации о человеке:
var person = {}; // пока пустой
Основные операции с объектами — это создание, получение и удаление свойств.
Для обращения к свойствам используется запись «через точку», вида объект.свойство, например:

// при присвоении свойства в объекте автоматически создаётся "ящик" // с именем "name" и в него записывается содержимое 'Вася' person.name = 'Вася';
person.age = 25; // запишем ещё одно свойство: с именем 'age' и значением 25
Значения хранятся «внутри» ящиков. Обратим внимание — любые значения, любых типов: число, строка — не важно.
Чтобы прочитать их — также обратимся через точку:
alert( person.name + ': ' + person.age ); // "Вася: 25"
Удаление осуществляется оператором delete:
delete person.age;
Осталось только свойство name:
Следующая операция:
4. Проверка существования свойства с определенным ключом.
Для проверки существования свойства в объекте есть оператор in.
Его синтаксис: "prop" in obj, причем имя свойства — в виде строки, например:
if ("name" in person) {
alert( "Свойство name существует!" );
}
Впрочем, чаще используется другой способ — сравнение значения с undefined.
Дело в том, что в JavaScript можно обратиться к любому свойству объекта, даже если его нет.
Ошибки не будет.
Но если свойство не существует, то вернется специальное значение undefined:
var person = {};
alert( person.lalala ); // undefined, нет свойства с ключом lalala
Таким образом мы можем легко проверить существование свойства — получив его и сравнив с undefined:
var person = { name: "Василий"
};
alert( person.lalala === undefined ); // true, свойства нет alert( person.name === undefined ); // false, свойство есть.

Разница между проверками inи === undefined
Есть два средства для проверки наличия свойства в объекте: первое — оператор in, второе — получить его и сравнить его с undefined.
Они почти идентичны, но есть одна небольшая разница.
Дело в том, что технически возможно, что свойство есть и равно undefined:
var obj = {};
obj.test = undefined; // добавили свойство со значением undefined
// проверим наличие свойств test и заведомо отсутствующего blabla alert( obj.test === undefined ); // true
alert( obj.blabla === undefined ); // true
…При этом, как видно из кода, при простом сравнении наличие такого свойства будет неотличимо от его отсутствия.
Но оператор inгарантирует правильный результат:
var obj = {}; obj.test = undefined;
alert( "test" in obj ); // true alert( "blabla" in obj ); // false
Как правило, в коде мы не будем присваивать undefined, чтобы корректно работали обе
проверки. А в качестве значения, обозначающего неизвестность и неопределенность, будем использовать null.
Доступ через квадратные скобки
Существует альтернативный синтаксис работы со свойствами, использующий квадратные скобки
объект['свойство']:
var person = {};
person['name'] = 'Вася'; // то же что и person.name = 'Вася'
Записи person['name']и person.nameидентичны, но квадратные скобки позволяют использовать в качестве имени свойства любую строку:
var person = {};
person['любимый стиль музыки'] = 'Джаз'; // то же что и person.name = 'Вася'
Такое присвоение было бы невозможно «через точку», так интерпретатор после первого пробела
подумает, что свойство закончилось, и далее выдаст ошибку:
person.любимый стиль музыки = 'Джаз'; // ??? ошибка
В обоих случаях, имя свойства обязано быть строкой. Если использовано значение другого типа
— JavaScript приведет его к строке автоматически.
Доступ к свойству через переменную
Квадратные скобки также позволяют обратиться к свойству, имя которого хранится в переменной:
var person = { age: 25
};
var key = 'age';
alert( person[key] ); // выведет person['age']
Вообще, если имя свойства хранится в переменной (var key = "age"), то единственный способ к нему обратиться — это квадратные скобки person[key].
Доступ через точку используется, если мы на этапе написания программы уже знаем название свойства. А если оно будет определено по ходу выполнения, например, введено посетителем и записано в переменную, то единственный выбор — квадратные скобки.
Объявление со свойствами
Объект можно заполнить значениями при создании, указав их в фигурных скобках: { ключ1:
значение1, ключ2: значение2, ... }.
Такой синтаксис называется литеральным (англ. literal).
Следующие два фрагмента кода создают одинаковый объект:
var menuSetup = { width: 300, height: 200, title: "Menu"
};
// то же самое, что:
var menuSetup = {}; menuSetup.width = 300; menuSetup.height = 200; menuSetup.title = 'Menu';
Названия свойств можно перечислять как в кавычках, так и без, если они удовлетворяют ограничениям для имён переменных.
Например:

var menuSetup = { width: 300, 'height': 200,
"мама мыла раму": true };
В качестве значения можно тут же указать и другой объект:
var user = { name: "Таня", age: 25, size: {
top: 90, middle: 60, bottom: 90
}
}
alert(user.name) // "Таня"
alert(user.size.top) // 90
Здесь значением свойства sizeявляется объект {top: 90, middle: 60, bottom: 90 }.
Компактное представление объектов
Hardcore coders only
Эта секция относится ко внутреннему устройству структуры данных. Она не обязательна к прочтению.
Браузер использует специальное «компактное» представление объектов, чтобы сэкономить память в том случае, когда однотипных объектов много.
Например, посмотрим на такой объект:
var user = { name: "Vasya", age: 25
};
Здесь содержится информация о свойстве nameи его строковом значении, а также о свойстве ageи его численном значении. Представим, что таких объектов много.
Получится, что информация об именах свойств nameи ageдублируется в каждом объекте. Чтобы этого избежать, браузер применяет оптимизацию.
При создании множества объектов одного и того же вида (с одинаковыми полями) интерпретатор выносит описание полей в отдельную структуру. А сам объект остаётся в виде непрерывной области памяти с данными.
Например, есть много объектов с полями nameи age:
{name: "Вася", age: 25} {name: "Петя", age: 22} {name: "Маша", age: 19}
...
Для их эффективного хранения будет создана структура, которая описывает данный вид объектов. Выглядеть она будет примерно так: <string name, number age>. А сами объекты будут представлены
в памяти только данными:
<структура: string name, number age>
Вася 25 Петя 22 Маша 19
При добавлении нового объекта такой структуры достаточно хранить значения полей, но не их имена. Экономия памяти — налицо.
А что происходит, если к объекту добавляется новое свойство? Например, к одному из них добавили свойство isAdmin:
user.isAdmin = true;
В этом случае браузер смотрит, есть ли уже структура, под которую подходит такой объект. Если нет
— она создаётся и объект привязывается к ней.
Эта оптимизация является примером того, что далеко не всё то, что мы пишем, один-в-один переносится в память.
Современные интерпретаторы очень стараются оптимизировать как код, так и структуры данных. Детали применения и реализации этого способа хранения варьируются от браузера к браузеру. О том, как это сделано в Chrome можно узнать, например, из презентации Know Your Engines . Она была некоторое время назад, но с тех пор мало что изменилось.
Итого
Объекты — это ассоциативные массивы с дополнительными возможностями:
●Доступ к элементам осуществляется:
●Напрямую по ключу obj.prop = 5
●Через переменную, в которой хранится ключ:
var key = "prop"; obj[key] = 5
●Удаление ключей: delete obj.name.
●Существование свойства может проверять оператор in: if ("prop" in obj), как правило, работает и просто сравнение if (obj.prop !== undefined).