Какие подводные камни есть у замыканий?
C замыканиями я знаком, знаю как их применить.
Недавно был на собеседовании и спросили какие недостатки у замыканий есть, а я не знаю. Хотелось бы узнать какие они у замыканий.
Пример с setTimeout показывать не надо. Как они работают я понимаю.
Я гуглил, был на https://javascript.info/ и https://developer.mozilla.org/. Не нашел ответа.
Решил посетить этот источник.
Хотелось бы с примером где есть недостаток.
Или ссылку на источник, буду благодарен.
Ответы (1 шт):
С замыканиями то всё хорошо, а вот люди несовершенны...
Вот хотел человек каждую секунду по числу, а получил 5 пятерок сразу:
for(var i=0;i<5;i++) {
setTimeout(()=>console.log(i), 1000)
console.log('privet')
}
- Если замыкание передается аргументом в какую-то функцию (здесь
setTimeout), то эта функция и определяет, когда и сколько раз будет запущено замыкание.setTimeoutвызвался в цикле 5 раз подряд почти одновременно. Каждый вызов закидывал замыкание в будущее на 1 секунду. Всеconsole.log('privet')сработали на секунду раньше всехconsole.log(i). varговорит о том, что переменная определена для окружающей функции, в цикле она меняется. Из замыкания будет видно текущее значение переменной. Т. к. всеconsole.log(i)выполнятся после цикла, они увидятiна момент окончания цикла (когдаiперестало подходить под условие).- если
varзаменить наlet, то у каждой итерации цикла (и у каждого из 5-и созданных замыканий) будет свояi, иconsole.log(i)напечатает числа от 0 до 4.
Еще this вечно чему попало равен в function(){...
В function(){ this не замыкается. В this попадает объект, который стоял до . при вызове функции: iWillBeThisInside.fun(), a если вызывалось просто fun(), то глобальный объект (часто window).
Возможно, это было настолько частой ошибкой, что при введении стрелочных функций (=>) сделали по-другому. Здесь this внутри будет такой же, как снаружи, при создании замыкания.
И всё бы хорошо, но определения методов классов ведут себя, как просто function. Так что, мучаемся ... используем .bind(this) дальше.
Из объективных недостатков:
У замыканий есть накладные расходы на создание и запуск. По сути, при создании замыкания создается объект. Например, while работает быстрее forEach. Эти накладные расходы могут иметь значение при оптимизации тяжелых вычислений, или хранении в памяти большого количества объектов-замыканий. Для обычного кода разница не будет заметна, и преждевременной оптимизации лучше избегать, отдавая предпочтение ясности (надежности) кода.