Javascript进阶---闭包
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript进阶---闭包相关的知识,希望对你有一定的参考价值。
维基:
在计算机中,闭包(也称词法闭包或者函数闭包),是指一个函数或者函数的引用,与一个引用环境绑定在一起。这个引用环境是一个存储该函数每个非局部变量的表。
百度百科:
闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)
- 一个简单的例子
function outer(){ var localVal = 30; return function(){ return localVal; } } var func = outer (); func(); //调用func()函数,得到30
在outer()函数被调用之后,localVal未被释放,匿名函数执行的时候,仍能够调用外函数outer()中的localVal变量。(这就是一个简单的闭包)
- 闭包的优缺点
- 优点:灵活方便、可进行封装
- 不及时释放会造成是空间上的浪费、会造成内存泄漏、会造成性能上的消耗
- 其他例子
1 function count(){ 2 var arr = []; 3 for (var i = 1; i<=3; i++){ 4 arr.push(function(){ 5 return i*i; 6 }); 7 } 8 return arr; 9 } 10 var results = count(); 11 var res1=results[0]; 12 var res2=results[1]; 13 var res3=results[2]; 14 15 console.log(res1+"\n"+res2+"\n"+res3); 16 /*function (){ 17 return i*i; 18 } 19 function (){ 20 return i*i; 21 } 22 function (){ 23 return i*i; 24 } 25 */
- 注意在代码第4行中,push进数组的是匿名函数function函数体原封不动地放进了数组,变量 i 也没有进行取值运算
console.log(res1()+"\n"+res2()+"\n"+res3());/*16 16 16 */
-
- 因为在 “var results = count();” 执行之后,for 循环中的 i 值已经变为 4 ,现在调用,返回 i * i 的值自然是16
- 如果想返回我们“原本期望的值“1 4 9”的话,我们尝试做出小的改动
-
1 function count(){ 2 var arr = []; 3 for (var i = 1; i<=3; i++){ 4 arr.push(function(n){ 5 return function(){ 6 return n*n; 7 } 8 }(i)); //关键点在此处 9 } 10 return arr; 11 } 12 var results = count(); 13 var res1=results[0]; 14 var res2=results[1]; 15 var res3=results[2]; 16 17 console.log(res1+"\n"+res2+"\n"+res3); 18 /*function (){ 19 return i*i; 20 } 21 function (){ 22 return i*i; 23 } 24 function (){ 25 return i*i; 26 } 27 */ 28 console.log(res1()+"\n"+res2()+"\n"+res3());/* 1 4 9*/
- 我们再返回一个函数的同时使用“()”符号将函数就地执行了,这个要才能够保证内部函数中的 i * i 返回的是当次循环的的 i 值。
4、其他笔记
- 因为Javscript不算是一门面对现对象的语言,所以无法直接封装私有变量,但利用闭包,我们可以模拟这个过程。
-
1 function create_sth(initial){ 2 var x = initial || 0 ; 3 return { 4 inc : function (){ 5 x + = 1; 6 return x; //返回的对象中包含着inc函数,该函数又携带着一个局部变量x。 7 } 8 } 9 }
- 换句话说,闭包就是携带状态的函数,并且它的状态可以对外界完全隐藏起来。
以上是关于Javascript进阶---闭包的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 精粹 基础 进阶函数和作用域(闭包作用域)
JavaScript中高级进阶推荐一个JavaScript进阶深入系列专题系列(涉及原型作用域执行上下文变量对象this闭包按值传递callapplybindnew继承等