大多数JavaScript开发人员使用 关闭 有意无意地。即使他们无意识地这么做了,在大多数情况下效果也很好。但是知道闭包可以在使用它们时更好地控制代码。学习闭包的另一个原因是,它是JavaScript开发人员面试中最常问的问题。 先决条件: : JavaScript中的变量作用域
让我们通过一个例子来了解闭包。
例1:
Javascript
// Explanation of closure /* 1 */ function foo() /* 2 */ { /* 3 */ var b = 1; /* 4 */ function inner(){ /* 5 */ return b; /* 6 */ } /* 7 */ return inner; /* 8 */ } /* 9 */ var get_func_inner = foo(); /* 10 */ console.log(get_func_inner()); /* 11 */ console.log(get_func_inner()); /* 12 */ console.log(get_func_inner()); |
说明: 值得注意的是 9号线 到 12号线 .在第9行,我们完成了 函数foo() 以及整个 函数内部() 返回并存储在 var get_func_inner ,由于7号线 返回内部 . [return语句不执行内部函数–函数仅在后跟()时执行,而是返回对函数的引用,因为JavaScript中的函数也是一个对象。]
我们可以访问变量 B 定义如下: 函数foo() 通过 函数内部() 因为后者在执行封闭函数时保留了封闭函数的作用域链,即内部函数知道 B 通过它的范围链。 这就是闭包,即内部函数可以访问外部函数变量以及所有全局变量。 上述代码的输出:
为了查看闭包中的变量和函数边界,我们可以这样写:
Javascript
/* 13 */ console.dir(get_func_inner); |
输出:
正如我们可以在范围部分中看到闭包中的变量一样。
关闭的定义:
在编程语言中,闭包(也称为词汇闭包或函数闭包)是在具有一级函数的语言中实现词汇范围的名称绑定的技术。从操作上讲,闭包是一个存储函数[a]和环境[1]的记录,它是一个映射,将函数的每个自由变量(在本地使用但在封闭范围内定义的变量)与创建闭包时名称所绑定的值或引用相关联。[b] -维基百科
或
换句话说,当子函数即使在父函数已经执行之后仍保留父作用域的环境时,就会创建闭包
现在让我们来看另一个例子。
例2:
Javascript
function foo(outer_arg) { function inner(inner_arg) { return outer_arg + inner_arg; } return inner; } var get_func_inner = foo(5); console.log(get_func_inner(4)); console.log(get_func_inner(3)); |
说明: 在上面的示例中,我们使用了参数函数,而不是默认函数。注意,即使我们已经完成了 傅(5) 我们可以进入 外_arg 来自内部函数的变量。在执行内部函数时,产生 外_arg 和 内_arg 如你所愿。
输出:
现在我们来看一个循环中的闭包示例。 在本例中,我们希望在数组的每个索引处存储一个匿名函数。
例3:
Javascript
// Outer function function outer() { var arr = []; var i; for (i = 0; i < 4; i++) { // storing anonymous function arr[i] = function () { return i; } } // returning the array. return arr; } var get_arr = outer(); console.log(get_arr[0]()); console.log(get_arr[1]()); console.log(get_arr[2]()); console.log(get_arr[3]()); |
输出:
说明: 你猜对答案了吗?在上面的代码中,我们创建了四个闭包,指向变量i,它是函数outer的局部变量。 我不记得它的价值 这个变量只有 要点 到变量或存储 参考 并因此返回当前值。在上面的代码中,当我们试图更新它的值时,它会反映给所有人,因为闭包存储了引用。
让我们看看编写上述代码的正确方法,以便在不同索引处获得不同的i值。
例4:
Javascript
// Outer function function outer() { function create_Closure(val) { return function () { return val; } } var arr = []; var i; for (i = 0; i < 4; i++) { arr[i] = create_Closure(i); } return arr; } var get_arr = outer(); console.log(get_arr[0]()); console.log(get_arr[1]()); console.log(get_arr[2]()); console.log(get_arr[3]()); |
输出:
说明: 在上面的代码中,我们在每次调用时更新函数create_Closure的参数。因此,我们在不同的指数下得到不同的i值。
注: 一下子理解闭包的概念可能有点困难,但是试着在不同的场景中尝试闭包,比如创建getter/setter、回调等等。
参考: 斯托扬·斯特凡诺夫的《面向对象的JavaScript》 本文由 苏米特·戈什 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。