- •Типы данных в es2015. Какие есть типы, какие из них примитивные, в чём разница и каковы особенности? Для каких есть литералы? Оператор typeof.
- •Тип данных Number. Его особенности, свойства, методы.
- •Тип данных String. Его особенности, свойства, методы. Строковые шаблоны.
- •Доступ к символам
- •Изменения строк
- •Смена регистра
- •Поиск подстроки
- •Отрицательные аргументы
- •Кодировка Юникод
- •Тип данных Symbol. Его особенности, свойства, методы.
- •Объявление
- •Глобальные символы
- •Использование символов
- •Приведение типов, неявное и явное. Взаимодействие типов с операторами.
- •Строковое преобразование
- •Численное преобразование
- •Специальные значения
- •Логическое преобразование
- •Встроенные модальные окна.
- •Массивы, их методы, особенности.
- •Методы pop/push, shift/unshift
- •Типизированные массивы. В чём их отличие, зачем они нужны, как с ними работать?
- •Типизированные массивы
- •Условные операторы, операторы циклов, переходы и метки.
- •Оператор вопросительный знак „?“
- •Варианты объявления функций в es2015, чем они отличаются?
- •Параметры по умолчанию
- •Оператор spread вместо arguments
- •Деструктуризация в параметрах
- •Область видимости, понятие замыкания.
- •Специальные значения this и arguments внутри функции.
- •Функции-стрелки не имеют своего this. Внутри функций-стрелок – тот же this, что и снаружи.
- •Методы и свойства функций. Как с ними работать и когда их применять?
- •Что такое каррирование, как оно работает и зачем нужно? Что такое мемоизация?
- •Работа с объектом типа Date.
- •Создание
- •Получение компонентов даты
- •Установка компонентов даты
- •Автоисправление даты
- •Преобразование к числу, разность дат
- •Форматирование и вывод дат
- •Метод Date.Now()
- •Объект как хеш-таблица.
- •Конфигурируемые свойства объекта.
- •Атрибуты свойств
- •Дескрипторы свойств
- •Перечислимые свойства объекта
- •Иммутабельность объектов. Копирование объектов. Что такое иммутабельность?
- •Копирование по ссылке
- •Особенности системы наследования объектов.
- •Наследование свойств
- •Наследование "методов"
- •Объектно-ориентированное программирование, принципы, парадигмы.
- •Псевдо-классовое наследование в es5 и es2015. Как организуется, на чём базируется, что изменилось в es2015.
- •Функциональное наследование.
- •Встроенные коллекции в es2015.
- •Обработка исключений. Принципы работы и когда следует использовать.
- •Таймеры и периодические вызовы.
- •Отмена исполнения clearTimeout
- •Цикл событий, принципы работы асинхронности.
- •Промисы (promise), назначение и особенности работы. Использование async/await.
- •Пример с setTimeout
- •Параллельное выполнение
- •Как мы будем их использовать?
- •Генераторы (generators). В чём заключаются, как работают, когда могут применяться?
- •Создание генератора
- •Генератор – итератор
- •Yield – дорога в обе стороны
- •Асинхронный код
- •Синтаксис диалекта регулярных выражений, доступный в es2015. Метасимволы, группировки, обратные ссылки, квантификаторы, символьный класс и выбор, позиционные проверки.
- •Использование регулярных выражений в конструкциях языка. Методы и свойства объекта регулярных выражений, методы строк, результаты операций.
Методы и свойства функций. Как с ними работать и когда их применять?
length
— количество агрументов, которые функция ожидает.
(function( a, b ){}).length; // 2
apply( thisArg[, argsArray] )
— метод вызывает функцию с заданным this и аргументами, переданными как массив.
Преимущество apply перед call отчётливо видно, когда мы формируем массив аргументов динамически. Например, в JavaScript есть встроенная функция Math.max(a, b, c...), которая возвращает максимальное значение из аргументов:
Math.max.apply( null, [1, 2, 3] ); // 3
call( thisArg[, arg1[, arg2[, ...]]] )
— метод вызывает функцию с заданным this и аргументами.
function showFullName() {
alert( this.firstName + " " + this.lastName );
}
var user = {
firstName: "Василий",
lastName: "Петров"
};
showFullName.call(user) // "Василий Петров"
После контекста в call можно передать аргументы для функции. Вот пример с более сложным вариантом showFullName, который конструирует ответ из указанных свойств объекта:
var user = {
firstName: "Василий",
surname: "Петров",
patronym: "Иванович"
};
function showFullName(firstPart, lastPart) {
alert( this[firstPart] + " " + this[lastPart] );
}
showFullName.call(user, 'firstName', 'surname') // "Василий Петров"
showFullName.call(user, 'firstName', 'patronym') // "Василий Иванович"
bind( thisArg[, arg1[, arg2[, ...]]] )
— (EcmaScript 5) создаёт новую функцию с привязкой к заданному this и предопределёнными агрументами, если заданы (они будут прибавлены к каждому вызову новой функции, причем встанут перед теми, которые указаны при вызове).
var user = {
firstName: "Вася",
sayHi: function() {
alert( this.firstName );
}
};
setTimeout(user.sayHi.bind(user), 1000); // "Вася"
Методы bind и call/apply близки по синтаксису, но есть важнейшее отличие. Методы call/apply вызывают функцию с заданным контекстом и аргументами. А bind не вызывает функцию. Он только возвращает «обёртку», которую мы можем вызвать позже, и которая передаст вызов в исходную функцию, с привязанным контекстом.
Метод func.bind(thisArg, ...) может создавать обёртку, которая фиксирует не только контекст, но и ряд аргументов функции. Например, есть функция умножения двух чисел mul(a, b):
function mul(a, b) {
return a * b;
};
При помощи bind создадим функцию double, удваивающую значения. Это будет вариант функции mul с фиксированным первым аргументом:
var double = mul.bind(null, 2);
double(3); // = mul(2, 3) = 6
double(4); // = mul(2, 4) = 8
double(5); // = mul(2, 5) = 10
При вызове double будет передавать свои аргументы исходной функции mul после тех, которые указаны в bind, то есть в данном случае после зафиксированного первого аргумента 2.
Что такое каррирование, как оно работает и зачем нужно? Что такое мемоизация?
Каррирование - это приём в функциональном программировании, позволяющий преобразовать функцию, заменив её несколько первых аргументов константными значениями, тем самым создав новую функцию с меньшим количеством аргументов на основе старой. Этот будет удобно применять в случае, когда первые несколько аргументов функции заранее известны, и указывать их при каждом вызове нет необходимости.
function sum(a, b) {
return a + b;
}
function sayTwoWords(word1, word2) {
console.log(word1 + " " + word2);
}
function curry(func, a) {
return function (b) {
return func(a, b);
};
}
var sayGoodbyeTo = curry(sayTwoWords, "Goodbye");
sayGoodbyeTo("Mary"); // "Goodbye Mary"
var minusThree = curry(sum, -3);
console.log(minusThree(13)); // 10
В JS функция при вызове может принимать произвольное количество аргументов, вне зависимости от того, сколько их было указанно при объявлении. Пользуясь этой возможностью, объявим куррирующую функцию с одним параметром func, в который будет передаваться каррируемая функция. Остальные же параметры будут значениями, на которые будут заменяться первые аргументы каррируемой функции. Эти значения мы будем извлекать из объекта arguments, в котором содержатся все значения аргументов функции, и записывать в массив. В возвращаемой функции нам необходимо вызвать каррируемую функцию, подставив в качестве первых аргументов значения из массива curryArgs, а в качестве остальных — значения, переданные в качестве параметров возвращаемой функции. Для этого воспользуемся методом apply, который позволяет вызвать функцию со значениями аргументов, которые переданы ему в массиве. Перед тем, как вызвать метод apply от каррируемой функции, преобразуем в массив объект arguments возвращаемой функции и склеим, при помощи метода concat, массив curryArgs c полученным массивом. Результат этой операции и передадим в качестве второго аргумента методу apply. В итоге функция curry примет вид:
function curry(func) {
var args = arguments, curryArgs = [];
for (var i = 1; i < args.length; i++) {
curryArgs[i - 1] = args[i];
}
return function () {
var argsArr = Array.prototype.slice.call(arguments, 0);
curryArgs = curryArgs.concat(argsArr);
return func.apply(this, curryArgs);
}
}
В ES2015 функцию каррирования можно записать короче:
function curry( func, ...curryArgs )
{
return ( ...rest ) =>
func( ...curryArgs, ...rest );
}
Примеры:
function multiply( x, y )
{
return x * y;
}
const double = curry( multiply, 2 );
double( 2 ); // 4
const double4 = ( x ) => multiply( x, 2 );
const double3 = ( y ) => multiply( 2, y );
Иногда наши рекурсивные или часто вызываемые функции очень сильно «тормозят» выполнение программы, потому что результаты промежуточных вычислений нигде не сохраняются, а вычисляются заново. Мемоизация — сохранение результатов выполнения функций для предотвращения повторных вычислений. Перед вызовом функции проверяется, вызывалась ли функция ранее: если не вызывалась, функция вызывается и результат её выполнения сохраняется; если вызывалась, используется сохранённый результат. Классическим примером для иллюстрации является функция, вычисляющая последовательность чисел Фибоначчи:
function fibonacci(n) {
if (n === 0 || n === 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
Для больших чисел n количество вызовов функции растёт очень быстро. Уже для n=50 это порядка 40 миллиардов вызовов. Используя идею мемоизации, то есть кеширования промежуточного результата, можно добиться уменьшения количества вызовов для n=50 до всего лишь 99:
var fibonacci = (function() {
var memo = {};
function f(n) {
var value;
if (n in memo) {
value = memo[n];
}
else {
if (n === 0 || n === 1)
value = n;
else
value = f(n - 1) + f(n - 2);
memo[n] = value;
}
return value;
}
return f;
})();
