The linked video explains why closure can inflict some performance hits starting about 11:08.
В основном, он говорит, что для каждой вложенной функции, он добавляет еще один объект в цепочке областей видимости и, следовательно, доступ к переменным за пределами закрытия займет еще больше времени.
Чтобы найти значение, связанное с переменной, interprer Javascript проходит следующим образом:
- поиск локального объекта области видимости
- если 1 не работает, поиск объекта родительской области
- если 2 не работал, поиск объекта родителя сфера родителя
- продолжать поиск родительских областей до
- вы ищете глобальный масштаб
- , и если он еще не найден, введите неопределенную переменную ошибку.
В обычной функции, чтобы найти переменную, вам нужно искать только верхнюю часть цепочки областей видимости. Заключение, с другой стороны, для поиска родительских переменных придется искать в цепочке видимости, иногда на нескольких уровнях. Например, если у вас были некоторые затворов, как это (обратите внимание, что это очень надуманный пример):
function a (x) {
function b (y) {
return (function (z) {
return x + y + z;
})(y + y);
}
return b(x + 3);
}
С внутренней функции, чтобы оценить выражение x + y + z
, он должен пройти три уровня в цепь цепочки, чтобы найти x, то она должна снова пройти цепочку областей действия на два уровня, чтобы найти y, а затем, наконец, один раз, чтобы найти z.В общей сложности ему пришлось искать шесть объектов в цепочке областей, чтобы вернуть окончательный результат.
Это неизбежно в замыканиях, потому что замыканиям всегда приходится обращаться к родительским переменным. Если бы они этого не сделали, было бы нецелесообразно использовать закрытие.
Также обратите внимание, что в Javascript есть значительные накладные расходы при создании функций, особенно закрытий. Возьмем, к примеру, это довольно простое замыкание:
function a(x) {
return function (y) {
return x + y;
}
}
И вы называете это несколько разные времена, как этот
var x = a(1);
var y = a(2);
var z = a(3);
alert(x(3)); // 4
alert(y(3)); // 5
alert(z(3)); // 6
Вы заметите, что функция возвращается из a
должен сохранить то, что было принято как аргумент в родительской функции даже после того, как родительская функция уже была вызвана. Это означает, что интерпретатор должен хранить в памяти то, что вы передали, в каждую функцию, которую вы вызвали до сих пор.
Просто помните: преждевременная оптимизация - это корень всего зла. Видео обсуждает, что делает JavaScript более совершенным, однако большинство JavaScript никогда не нуждается в оптимизации. Если у вас есть вызов функции, настроенной асинхронно после нажатия пользователем кнопки, пользователь никогда не заметит разницу между скоростью ответа 30 мс и скоростью ответа 40 мс. – zzzzBov
Ответы здесь хорошие. Помните, однако, что видео - пару лет, и может быть не так важно, как когда-то было. –