
- •Введение
- •Введение в 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

Сумма произвольного количества скобок
важность: 2
Напишите функцию sum, которая будет работать так:
sum(1)(2) == 3; // 1 + 2 sum(1)(2)(3) == 6; // 1 + 2 + 3 sum(5)( 1)(2) == 6 sum(6)( 1)( 2)( 3) == 0 sum(0)(1)(2)(3)(4)(5) == 15
Количество скобок может быть любым.
Пример такой функции для двух аргументов — есть в решении задачи Сумма через замыкание.
К решению
Создание объектов через «new»
Обычный синтаксис {...}позволяет создать один объект. Но зачастую нужно создать много однотипных объектов.
Для этого используют «функции-конструкторы», запуская их при помощи специального оператора new.
Конструктор
Конструктором становится любая функция, вызванная через new.
Например:
function Animal(name) { this.name = name; this.canWalk = true;
}
var animal = new Animal("ёжик");
Технически, любую функцию можно вызвать при помощи new. Но при этом она работает несколько иным образом, чем обычно, поэтому функции, предназначенные к вызову через new, называют с большой буквы.
Алгоритм работы функции, запущенной через new:
1.Автоматически создается новый пустой объект.
2.Ключевое слово thisполучает ссылку на этот объект.

3.Функция выполняется. Как правило, она модифицирует this, добавляет методы, свойства.
4.Возвращается this.
Врезультате вызова new Animal("ёжик");получаем такой объект:
animal = { name: "ёжик", canWalk: true
}
Иными словами, при вызове new Animalпроисходит что-то в таком духе (первая и последняя строка
— это то, что делает интерпретатор):
function Animal(name) { // this = {}
// в this пишем свойства, методы this.name = name;
this.canWalk = true;
// return this
}
Правила обработки return
Как правило, конструкторы ничего не возвращают. Их задача — записать всё, что нужно, в this, который автоматически станет результатом.
Но если явный вызов returnвсё же есть, то применяется простое правило:
●При вызове returnс объектом, будет возвращён он, а не this.
●При вызове returnс примитивным значением, оно будет отброшено.
Иными словами, вызов returnс объектом вернёт объект, а с чем угодно, кроме объекта — возвратит, как обычно, this.
Например, возврат объекта:
function BigAnimal() { this.name = "Мышь";
return { name: "Годзилла" }; // < возвратим объект
}
alert( new BigAnimal().name ); // Годзилла, получили объект вместо this
А вот пример с возвратом строки:

function BigAnimal() { this.name = "Мышь";
return "Годзилла"; // < возвратим примитив
}
alert( new BigAnimal().name ); // Мышь, получили this (а Годзилла пропал)
Эта особенность работы newпрописана в стандарте, но используется она весьма редко.
Можно без скобок
Кстати, при вызове newбез аргументов скобки можно не ставить:
var animal = new BigAnimal; // < без скобок
// то же самое что
var animal = new BigAnimal();
Не сказать, что выбрасывание скобок — «хороший стиль», но такой синтаксис допустим стандартом.
Создание методов в конструкторе
Использование функций для создания объекта дает большую гибкость. Можно передавать конструктору параметры, определяющие как его создавать, и он будет «клепать» объекты заданным образом.
Добавим в создаваемый объект ещё и метод.
Например, new User(name)создает объект с заданным значением свойства nameи методом sayHi:
function User(name) { this.name = name;
this.sayHi = function() {
alert( "Моё имя: " + this.name ); };
}
var ivan = new User("Иван");
ivan.sayHi(); // Моё имя: Иван
/*
ivan = {
name: "Иван", sayHi: функция
}
*/
Локальные переменные

В функции-конструкторе бывает удобно объявить вспомогательные локальные переменные и
вложенные функции, которые будут видны только внутри:
function User(firstName, lastName) {
//вспомогательная переменная var phrase = "Привет";
//вспомогательная вложенная функция function getFullName() {
return firstName + " " + lastName;
}
this.sayHi = function() {
alert( phrase + ", " + getFullName() ); // использование };
}
var vasya = new User("Вася", "Петров"); vasya.sayHi(); // Привет, Вася Петров
Мы уже говорили об этом подходе ранее, в главе Локальные переменные для объекта.
Те функции и данные, которые должны быть доступны для внешнего кода, мы пишем в this— и к ним можно будет обращаться, как например vasya.sayHi(), а вспомогательные, которые нужны только внутри самого объекта, сохраняем в локальной области видимости.
Итого
Объекты могут быть созданы при помощи функций-конструкторов:
●Любая функция может быть вызвана с new, при этом она получает новый пустой объект в качестве this, в который она добавляет свойства. Если функция не решит возвратить свой объект, то её результатом будет this.
●Функции, которые предназначены для создания объектов, называются конструкторами. Их названия пишут с большой буквы, чтобы отличать от обычных.
Задачи
Две функции один объект
важность: 2
Возможны ли такие функции Aи Bв примере ниже, что соответствующие объекты a,bравны (см. код ниже)?
function A() { ... } function B() { ... }
var a = new A; var b = new B;
alert( a == b ); // true

Если да — приведите пример кода с такими функциями.
К решению
Создать Calculator при помощи конструктора
важность: 5
Напишите функцию-конструктор Calculator, которая создает объект с тремя методами:
●Метод read()запрашивает два значения при помощи promptи запоминает их в свойствах объекта.
●Метод sum()возвращает сумму запомненных свойств.
●Метод mul()возвращает произведение запомненных свойств.
Пример использования:
var calculator = new Calculator(); calculator.read();
alert( "Сумма=" + calculator.sum() ); alert( "Произведение=" + calculator.mul() );
Запустить демо
Открыть песочницу с тестами для задачи.
К решению
Создать Accumulator при помощи конструктора
важность: 5
Напишите функцию-конструктор Accumulator(startingValue). Объекты, которые она создает, должны хранить текущую сумму и прибавлять к ней то, что вводит посетитель.
Более формально, объект должен:
●Хранить текущее значение в своём свойстве value. Начальное значение свойства valueставится конструктором равным startingValue.
●Метод read()вызывает prompt, принимает число и прибавляет его к свойству value.
Таким образом, свойство valueявляется текущей суммой всего, что ввел посетитель при вызовах метода read(), с учетом начального значения startingValue.
Ниже вы можете посмотреть работу кода:

var accumulator = new Accumulator(1); // начальное значение 1 accumulator.read(); // прибавит ввод prompt к текущему значению accumulator.read(); // прибавит ввод prompt к текущему значению alert( accumulator.value ); // выведет текущее значение
Запустить демо
Открыть песочницу с тестами для задачи.
К решению
Создайте калькулятор
важность: 5
Напишите конструктор Calculator, который создаёт расширяемые объекты-калькуляторы.
Эта задача состоит из двух частей, которые можно решать одна за другой.
1.Первый шаг задачи: вызов calculate(str)принимает строку, например «1 + 2», с жёстко
заданным форматом «ЧИСЛО операция ЧИСЛО» (по одному пробелу вокруг операции), и возвращает результат. Понимает плюс +и минус .
Пример использования:
var calc = new Calculator;
alert( calc.calculate("3 + 7") ); // 10
2.Второй шаг — добавить калькулятору метод addMethod(name, func), который учит калькулятор новой операции. Он получает имя операции nameи функцию от двух аргументов func(a,b), которая должна её реализовывать.
Например, добавим операции умножить *, поделить /и возвести в степень **:
var powerCalc = new Calculator; powerCalc.addMethod("*", function(a, b) {
return a * b; });
powerCalc.addMethod("/", function(a, b) { return a / b;
});
powerCalc.addMethod("**", function(a, b) { return Math.pow(a, b);
});
var result = powerCalc.calculate("2 ** 3"); alert( result ); // 8
●Поддержка скобок и сложных математических выражений в этой задаче не требуется.
●Числа и операции могут состоять из нескольких символов. Между ними ровно один пробел.