Замыкания — одна из трех гор JS, очень неприятная тема для многих фронтенд-разработчиков. Эта статья займет около 9 минут, чтобы сравнить и понять замыкания с 4 наборами очень простых примеров, которые могут изменить ваше прежнее понимание замыканий.
Прежде чем сравнивать случай, позвольте мне высказать свое мнение:Закрытия - это просто явление. Здесь мы не должны пытаться использовать официальное определение, чтобы понять значение замыкания бессловесным способом, что приведет к недопониманию. Наша цель — выяснить условия, при которых происходит явление замыкания при выполнении функции. Итак, давайте использовать 4 группы (всего 9 демонстраций, вы можете читать по одной в минуту) кейс-анализа, если вы можете понять, как происходит явление замыкания после прочтения, то все готово.
Первая группа, используйте ссылки на глобальные переменные для выполнения
var m, n;//全局变量
function outer_a1() {
var num = 10;
function inner() {
console.log(num) //打印了outer_a1中定义的num
debugger
}
m = inner;
}
outer_a1();
m();
function outer_a2() {
var num = 10;
function inner() {
console.log("just console") //只做了简单的打印
debugger
}
n = inner;
}
outer_a2();
n();
Приведенные выше два изображения являются снимками экрана консоли Chrome, когда выполняются external_a1() и external_a2() соответственно, а затем выполняются m() и n().После достижения точки останова отладчика мы видим, что появляется первый из них Closure And включает переменную num:10, вторая картинка не появляется Closure. Без объяснения продолжайте вторую группу сравнений случаев.
Вторая группа, внутренние прямого исполнения
function outer_b1() {
var num = 15;
function inner() {
console.log(num) //打印了outer_b1中定义的num
debugger
}
inner()
}
outer_b1();
function outer_b2() {
var num = 15;
function inner() {
console.log("just console") //只做了简单的打印
debugger
}
inner()
}
outer_b2();
Вторая группа похожа на первую группу, за исключением того, что inner выполняется непосредственно в external_b1 и external_b2.Мы можем обнаружить, что Closure первым генерирует переменную num: 15 (Примечание: если var num = 15; помещается во inner После выполнения () по правилу продвижения переменных значение переменной num в Замыкании не определено), при этом второй не генерирует Замыкание, а третья группа продолжает:
Третья группа, вернитесь и затем выполните
function outer_c1(s) {
var num = 20;
function inner() {
console.log(s + num) //打印包含了outer_c1形参s和定义的num
debugger
}
return inner
}
outer_c1()();
function outer_c2(s) {
var num = 20;
function inner() {
console.log("just console") //只做了简单的打印
debugger
}
return inner
}
outer_c2()();
Третья группа использовала return для возврата внутреннего внутреннего, а затем выполнила external_c1()() и external_c2()() соответственно для запуска внутреннего внутреннего и обнаружила, что первый сгенерировал замыкание, а второй — нет. первый формальный параметр s, который ссылается на external_c1, поэтому переменная в Closure также имеет дополнительный s, но фактический параметр не передается при выполнении external_c1(), поэтому значение s не определено.
Эти три группы случаев на самом деле очень похожи.Единственная разница между двумя демонстрациями в каждой группе заключается в том, что первая демонстрация печатает частные локальные переменные, принадлежащие внешней функции, а вторая демонстрация просто выполняет простую печать. На этом этапе можно приблизительно определить, что генерация замыкания не особо связана с методом выполнения, а определяется тем, ссылается ли внутренняя функция на приватные переменные внешней функции. Затем посмотрите на последнюю группу:
Группа 4, несколько способов вместе
var x, y, z; //全局变量
function outer_d1(s) {
var num = 25;
function inner1() {
console.log(s) //打印形参s
debugger
}
y = inner1;
function inner2() {
console.log("just console") //只做了简单的打印
debugger
}
inner2();
function inner3() {
console.log(num) //打印定义的num
debugger
}
return inner3
}
outer_d1("i am x");
function outer_d2(s) {
var num = 25;
function inner1() {
console.log(s) //打印形参s
debugger
}
function inner2() {
console.log("just console") //只做了简单的打印
debugger
}
function inner3() {
console.log(num) //打印定义的num
debugger
}
inner2();
}
outer_d2("i am y");
function outer_d3(s) {
var num = 30;
function inner1() {
console.log("just console") //只做了简单的打印
debugger
}
z = inner1;
function inner2() {
console.log("just console") //只做了简单的打印
debugger
}
inner2();
function inner3() {
console.log("just console") //只做了简单的打印
debugger
}
return inner3
}
outer_d3("i am z")();
z();
Эта группа сравнивает три примера.Первая группа и вторая группа немного отличаются.В первой группе в конечном итоге выполняются все внутренние функции, а во второй группе выполняется только одна внутренняя2,. Результат запуска не будет отображаться, вы можете запустить его самостоятельно, и вы обнаружите следующее явление:
- 1. При переходе к каждому внутреннему элементу external_d1 будет Closure, а переменные Closure — num и s;
- 2. При запуске к inner2 внутри external_d2 тоже будет Closure, а переменные Closure тоже num и s;
- 3. Нет Замыкания при переходе к каждому внутреннему внутреннему внешнему_d3.
Несложно понять, что external_d3 не генерирует замыканий, потому что внутренние функции просто печатаются, но почему inner2 внутри external_d1 и external_d2 тоже просто печатаются, а замыкания тоже генерируются в процессе выполнения?
Это связано с тем, что их внутренние inner1 и inner3 относятся к закрытым переменным внешнего.В настоящее время external_d1 и external_d2 стали замыканием, поэтому, даже если inner2 ничего не печатает, оно уже находится в этой среде замыкания.Выполнить, когда сгенерированный Clouser Также видно, что переменные в сформированном Clouser являются локальными частными переменными внешнего, на которые ссылаются все внутренние функции.
Суммировать
По приведенным выше четырем наборам сравнительных случаев можно сделать вывод, что замыкание - это явление, порожденное выполнением функций при определенных обстоятельствах.Условиями этого явления являются:Когда функция (внешняя) выполняется, на ее формальные параметры или частные переменные (число, s) ссылается внутренняя функция (внутренняя).. Когда это условие выполняется, то этовнешний сформирует замыкание, переменные, содержащиеся в этом замыкании, — это все формальные параметры и локальные переменные, на которые ссылается внутренняя функция, когда работает сама внешняя. Это не имеет ничего общего с тем, возвращается внутренняя функция или нет, выполняется или не выполняется.