[JavaScript, Программирование] 7 вопросов про замыкания в JavaScript (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабр. Для будущих студентов курса "JavaScript Developer. Professional" подготовили перевод интересного материала. В рамках набора студентов на курс приглашаем принять участие в открытом карьерном вебинаре, где преподаватель расскажет о себе, своём профессиональном опыте и ответит на вопросы касательно карьеры в этой области.
7 Вопросов из интервью по замыканиям (closures) в JavaScript. Можете ли вы ответить на них?Каждый разработчик JavaScript должен знать, что такое замыкание (closure). Во время собеседования по кодированию JavaScript есть большая вероятность, что вас спросят о концепции замыкания.Я составил список из 7 интересных и наиболее сложных вопросов по замыканиям в JavaScript.Возьмите карандаш, лист бумаги и постарайтесь ответить на вопросы, не глядя на ответы и не запуская код. По моим подсчетам, вам понадобится около 30 минут.Развлекайтесь!Если вам нужно освежить свои знания о замыкании, я рекомендую ознакомится с публикацией A Simple Explanation of JavaScript Closures (Простое объяснение замыканиям в JavaScript).СодержаниеВопрос 1: Замыкания развязывают твои руки Вопрос 2: Утерянные параметрыВопрос 3: Кто есть ктоВопрос 4: Хитроумное замыканиеВопрос 5: Правильное или неправильное сообщениеВопрос 6: Восстановление инкапсуляции (Restore encapsulation)Вопрос 7: Умное перемножениеРезюмеВопрос 1: Замыкания развязывают твои руки Рассмотрим следующие функции: clickHandler, immediate, и delayReload:
let countClicks = 0;
button.addEventListener('click', function clickHandler() {
countClicks++;
});
const result = (function immediate(number) {
const message = `number is: ${number}`;
return message;
})(100);
setTimeout(function delayedReload() {
location.reload();
}, 1000);
Какие из этих 3 функций получают доступ к переменным внешней области видимости (outer scope)?Расширенный ответ
- clickHandler обращается к переменной countClicks из внешней области видимости.
- immediate не обращается ни к каким переменным из внешней области видимости.
- delayReload обращается к глобальной переменной location из глобальной области видимости (так же известной как крайняя область видимости (outermost scope)).
Вопрос 2: Утерянные параметрыЧто будет записано в консоль для следующего фрагмента кода (code snippet):
(function immediateA(a) {
return (function immediateB(b) {
console.log(a); // What is logged?
})(1);
})(0);
Расширенный ответ:0 записывается на консоль. Посмотрите демо.immediateA вызывается с аргументом 0, таким образом, параметр равен 0.Функция immediateB, будучи вложенной в функцию immediateA, является замыканием, которое захватывает переменную a из внешней области видимости immediateA, где a равно 0. Таким образом, console.log(a) записывает в журнал 0.Вопросы 3: Кто есть ктоЧто будет записано в консоль для следующего фрагмента кода (code snippet):
let count = 0;
(function immediate() {
if (count === 0) {
let count = 1;
console.log(count); // What is logged?
}
console.log(count); // What is logged?
})();
Расширенный ответ:1 и 0 записываются в консоль. Посмотрите демо.Первое утверждение let count = 0 объявляет переменную count.immediate() — это замыкание, которое захватывает переменную count из внешней области видимости. Внутри области видимости функции immediate() count равна 0.Однако внутри этого условия другая команда let count = 1 объявляет count локальной переменной, которая перезаписывает count из внешней области видимости. Первая console.log(count) записывает 1.Вторая console.log(count) записывает 0, так как здесь переменная count доступна из внешней области видимости.Вопрос 4: Хитроумное замыканиеЧто будет записано в консоль в следующем фрагменте кода (code snippet):
for (var i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i); // What is logged?
}, 1000);
}
Расширенный ответ:3, 3, 3 записано на консоль. Посмотрите демо.Фрагмент кода выполняется в 2 этапа.Фаза 1
- for() выполняет итерацию 3 раза. Во время каждой итерации создается новая функция log(), которая захватывает переменную i. setTimout() планирует исполнение log() через 1000мс.
- Когда цикл for() завершается, переменная i имеет значение 3.
Фаза 2Вторая фаза происходит после 1000 мс:
- setTimeout() выполняет запланированные функции log(). log() считывает текущее значение переменной i, которое равно 3, и записывает в консоль 3.
Поэтому 3, 3, 3 записывается в консоль.Дополнительная задача: как бы вы изменили в этом примере сообщение для консоли со значениями 0, 1, 2 ? Запишите ваше решение в комментариях ниже!Вопрос 5: Правильное или неправильное сообщениеЧто будет записано в консоль в следующем фрагменте кода (code snippet):
function createIncrement() {
let count = 0;
function increment() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement();
increment();
increment();
increment();
log(); // What is logged?
Расширенный ответ:'Count is 0' записывается в консоль. Посмотрите демо.Функция increment() вызывалась 3 раза, в итоге увеличивая count до значения 3.Переменная message существует в рамках функции createIncrement(). Ее начальное значение 'Count is 0'. Однако, даже если переменная count была увеличена несколько раз, переменная message всегда имеет значение 'Count is 0'.Функция log() — это закрытие, которое захватывает переменную message из области видимости createIncrement(). console.log(message) записывает 'Count is 0' в консоль.Дополнительная задача: как бы вы исправили функцию log(), чтобы она возвращала сообщение, имеющее фактическое значение count? Запишите ваше решение в комментариях ниже!Вопрос 6: Восстановление инкапсуляции (Restore encapsulation)Следующая функция createStack() создает элементы структуры стековых данных:
function createStack() {
return {
items: [],
push(item) {
this.items.push(item);
},
pop() {
return this.items.pop();
}
};
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => [10]
stack.items = [10, 100, 1000]; // Encapsulation broken!
Стек работает, как и ожидалось, но с одной маленькой проблемой. Любой может изменить массив элементов напрямую, потому что свойство stack.items открыто.Это неприятная деталь, так как она нарушает инкапсуляцию стека: только методы push() и pop() должны быть публичными, а stack.items или любые другие элементы не должны быть доступны.Рефакторизуйте описанную выше реализацию стека, используя концепцию замыкания, так, чтобы не было возможности доступа к массиву items вне области видимости функции createStack():
function createStack() {
// Write your code here...
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => undefined
Расширенный ответ:Вот возможный рефакторинг (refactoring) функции createStack():
function createStack() {
const items = [];
return {
push(item) {
items.push(item);
},
pop() {
return items.pop();
}
};
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => undefined
Посмотрите демо.items был перемещен в переменную внутри области видимости createStack().Благодаря этому изменению, за пределами области видимости createStack(), теперь нет способа получить доступ к массиву items или изменить его. Элементы сейчас являются приватной переменной, а стек инкапсулирован: только методы push() и pop() являются публичными.Методы push() и pop(), будучи замкнутыми, захватывают переменную items из области видимости функции createStack().Вопрос 7: Умное перемножениеНапишите функцию multiply(), которая умножает 2 числа:
function multiply(num1, num2) {
// Write your code here...
}
Если multiply(num1, numb2) будет вызвана с 2 аргументами, то она должна вернуть умножение 2 аргументов.Но в том случае, если вызывается 1 аргумент const anotherFunc = multiply(numb1), то функция должна возвращать другую функцию. Возвращаемая функция при вызове anotherFunc(num2) выполняет умножение num1 * num2.
multiply(4, 5); // => 20
multiply(3, 3); // => 9
const double = multiply(2);
double(5); // => 10
double(11); // => 22
Расширенный ответ:Вот возможная имплементация функции multiply():
function multiply(number1, number2) {
if (number2 !== undefined) {
return number1 * number2;
}
return function doMultiply(number2) {
return number1 * number2;
};
}
multiply(4, 5); // => 20
multiply(3, 3); // => 9
const double = multiply(2);
double(5); // => 10
double(11); // => 22
Посмотрите демо.Если параметр number2 не является undefined, то функция просто возвращает number1*number2.Но если number2 является undefined, то это означает, что функция multiply() была вызвана с одним аргументом. В таком случае вернем функцию doMultiply(), которая при последующем вызове выполняет фактическое умножение.doMultiply() является замыкающей, поскольку она захватывает переменную number1 из области видимости функции multiply().РезюмеСравните ваши ответы с ответами в статье:
- Если вы правильно ответили на 5 или более вопросов, у вас есть хорошее представление о замыканиях.
- Если вы правильно ответили менее чем на 5 вопросов, вам нужно хорошенько освежить тему замыкания,. Я рекомендую изучить мой пост A Simple Explanation of JavaScript Closures (Простое объяснение замыкания в JavaScript).
Готовы к новому испытанию? Попробуйте ответить на 7 вопросов в интервью по ключевому слову "this" в JavaScript.
===========
Источник:
habr.com
===========
===========
Автор оригинала: Dmitri Pavlutin
===========Похожие новости:
- [Программирование, C++, Алгоритмы] Ленивые операции над множествами в C++
- [Open source, Программирование, Геоинформационные сервисы, Визуализация данных, Научно-популярное] Геология XXI века: от реальности к виртуальности
- [Программирование, C++, Алгоритмы] Ленивые итераторы и диапазоны в C++
- [PHP, Программирование] Работа с заказом через админку OpenCart, взгляд изнутри
- [JavaScript, Анализ и проектирование систем, Алгоритмы, Обработка изображений, Машинное обучение] Мы создали Web приложение для определения лиц и масок для Google Chrome (перевод)
- [Разработка веб-сайтов, JavaScript, ReactJS] Реализация архитектуры Redux на MobX. Часть 2: «Пример на MobX»
- [Программирование, GTK+, Разработка под Linux] Пишем онлайн-радио на языке Vala
- [Программирование] Факториал 100 через рекурсию процесса в Camunda
- [Разработка веб-сайтов, Программирование, HTML, Лайфхаки для гиков] 5 HTML-трюков, о которых никто не говорит (перевод)
- [CSS, JavaScript, HTML] Веб-компоненты проще, чем вы думаете (перевод)
Теги для поиска: #_javascript, #_programmirovanie (Программирование), #_javascript, #_closure, #_interview, #_blog_kompanii_otus (
Блог компании OTUS
), #_javascript, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:00
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабр. Для будущих студентов курса "JavaScript Developer. Professional" подготовили перевод интересного материала. В рамках набора студентов на курс приглашаем принять участие в открытом карьерном вебинаре, где преподаватель расскажет о себе, своём профессиональном опыте и ответит на вопросы касательно карьеры в этой области.
7 Вопросов из интервью по замыканиям (closures) в JavaScript. Можете ли вы ответить на них?Каждый разработчик JavaScript должен знать, что такое замыкание (closure). Во время собеседования по кодированию JavaScript есть большая вероятность, что вас спросят о концепции замыкания.Я составил список из 7 интересных и наиболее сложных вопросов по замыканиям в JavaScript.Возьмите карандаш, лист бумаги и постарайтесь ответить на вопросы, не глядя на ответы и не запуская код. По моим подсчетам, вам понадобится около 30 минут.Развлекайтесь!Если вам нужно освежить свои знания о замыкании, я рекомендую ознакомится с публикацией A Simple Explanation of JavaScript Closures (Простое объяснение замыканиям в JavaScript).СодержаниеВопрос 1: Замыкания развязывают твои руки Вопрос 2: Утерянные параметрыВопрос 3: Кто есть ктоВопрос 4: Хитроумное замыканиеВопрос 5: Правильное или неправильное сообщениеВопрос 6: Восстановление инкапсуляции (Restore encapsulation)Вопрос 7: Умное перемножениеРезюмеВопрос 1: Замыкания развязывают твои руки Рассмотрим следующие функции: clickHandler, immediate, и delayReload: let countClicks = 0;
button.addEventListener('click', function clickHandler() { countClicks++; }); const result = (function immediate(number) {
const message = `number is: ${number}`; return message; })(100); setTimeout(function delayedReload() {
location.reload(); }, 1000);
(function immediateA(a) {
return (function immediateB(b) { console.log(a); // What is logged? })(1); })(0); let count = 0;
(function immediate() { if (count === 0) { let count = 1; console.log(count); // What is logged? } console.log(count); // What is logged? })(); for (var i = 0; i < 3; i++) {
setTimeout(function log() { console.log(i); // What is logged? }, 1000); }
function createIncrement() {
let count = 0; function increment() { count++; } let message = `Count is ${count}`; function log() { console.log(message); } return [increment, log]; } const [increment, log] = createIncrement(); increment(); increment(); increment(); log(); // What is logged? function createStack() {
return { items: [], push(item) { this.items.push(item); }, pop() { return this.items.pop(); } }; } const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5 stack.items; // => [10] stack.items = [10, 100, 1000]; // Encapsulation broken! function createStack() {
// Write your code here... } const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5 stack.items; // => undefined function createStack() {
const items = []; return { push(item) { items.push(item); }, pop() { return items.pop(); } }; } const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5 stack.items; // => undefined function multiply(num1, num2) {
// Write your code here... } multiply(4, 5); // => 20
multiply(3, 3); // => 9 const double = multiply(2); double(5); // => 10 double(11); // => 22 function multiply(number1, number2) {
if (number2 !== undefined) { return number1 * number2; } return function doMultiply(number2) { return number1 * number2; }; } multiply(4, 5); // => 20 multiply(3, 3); // => 9 const double = multiply(2); double(5); // => 10 double(11); // => 22
=========== Источник: habr.com =========== =========== Автор оригинала: Dmitri Pavlutin ===========Похожие новости:
Блог компании OTUS ), #_javascript, #_programmirovanie ( Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:00
Часовой пояс: UTC + 5