Js闭包

闭包前要了解的知识 

1. 函数作用域

(1).Js语言特殊之处在于函数内部可以直接读取全局变量

<script type="text/javascript">
var n=100;
function parent(){
alert(n);
}
parent();//
</script>

如果在php里

<?php
$n=100;
function parent(){
echo $n;
}
parent();//会报错 n未定义
?>

(2).在函数外部无法读取函数内的局部变量

<script type="text/javascript">
function parent(){
var m=50;
}
parent();
alert(m);//报错 m未定义
</script>

注意函数内部声明变量时一定要加var,否则就声明了一个全局变量

function parent(){
m=50;
}
parent();
alert(m);//
//当然在php里更是如此了,
<?php
function parent(){
global $m;//全局 ,定义与赋值要分开
$m=50;
}
parent();
echo $m;//
?>
//没global的话,一样会报没定义的错误

有时,需要得到函数内部的的局部变量,就需要变通的方法实现

利用js变量作用域的特点,如在函数内部定义子函数,对于子函数来说,父函数就是它的全局,子函数可以访问父函数里的变量(对于整个js代码来说又是局部变量)

<script type="text/javascript">
function parent(){
var m=50;
function son(){
alert(m);
}
return son;
}
var s=parent();//将结果保存在全局里
s();//
</script>

Parent内部所有局部变量对其子函数来说都是可见的,但其子函数内的局部变量对其父函数是不可见的,这就是js特有的链式作用域结构,子对象会一级一级地向上查找所有父对象的变量,父对象的所有变量对子对象都是可见的,反之不成立!

上面的son函数就是闭包

有些同学可能这样

function parent(){
var m=50;
function son(){
alert(m);
}
}
parent();
son()//会报 函数son未定义

注意 在javascript里,在函数里声明的函数都是局部的,函数运行完后就释放了

注意这点与php的区别

<?php
function parent(){
function son(){
$m=50;
echo $m;
}
}
parent();
son();//输出50 不会报错
?>

闭包

函数内部定义函数,连接函数内部和外部的桥梁

闭包的作用有2个:

一是前面提到的读取函数内部的变量,

二是让这些变量的值保存在内存中,实现数据共享

下面是几个闭包的例子

<script type="text/javascript">
var cnt=(function(){
var i=0;
return function(){
alert(i);
i++;
}
})();
cnt();//
cnt();//
cnt();//
cnt();// </script>

把匿名函数的执行结果(即对里面子函数的声明赋给全局变量cut),i就保存在内存里了

执行cut()时就直接从内存取值了,i只有cnt()函数才能调用,直接alert(i)是不行的

还可以向闭包内传参

var cnt=(function(num){
return function(){
alert(num);
num++;
}
})(5);
cnt();//
cnt();//
cnt();//
//当然还可以调用时传参
var cnt=(function(){
var i=0;
return function(num){
num+=i;
alert(num);
i++;
}
})();
cnt(1);//
cnt(2);//
cnt(3);//

为了对闭包有更好的理解,我们看以下代码

比如我想返回一个数组,数组里面有5个函数,第一个函数弹出0,第二个弹出1...

代码如果这样写

function box(){
var arr=[];
for(i=0;i<5;i++){
arr[i]=function(){return i;}
}
return arr;
}
var a=box();
alert(a);//包含五个函数体的数组
alert(a[0]());
alert(a[1]());

弹出的函数体

function(){return i;}

}

最后这个i是4,之后++成为5

For循环停止

发现均弹出5,明显不符合我们的要求

解决方案1

自我即时执行里面的函数

function box(){
var arr=[];
for(i=0;i<5;i++){
arr[i]=(function(num){return i;})(i);
}
return arr;
}
var a=box();
for(var i=0;i<a.length;i++){
alert(a[i]);
}

但是我们发现 返回的数组里的元素是函数执行的结果,但我们想要的是函数

有得升级我们的代码

解决方案2 闭包实现

function box(){
var arr=[];
for(var i=0;i<5;i++){ arr[i]=(function(num){
return function(){return num;}
})(i); }
return arr;
} var arr=box(); for(var i=0;i<5;i++){ alert(arr[i]());//0,1,2,3,4
}

关键代码

arr[i]=(function(num){

return function(){return num;}

})(i);

i=0 时

arr[0]=(function(num){return function(){return num;}})(0);

1时

arr[1]=(function(num){return function(){return num;}})(1);

这就是闭包的好处!

最新文章

  1. mysql 找回密码方法
  2. python中的循环
  3. 164. Maximum Gap *HARD* -- 无序数组找出排序后连续元素的最大间隔
  4. 系统使用 aspose.cell , 使得ashx第一次访问会变很慢
  5. jqueryMobile
  6. next_permutation()函数 和 prev_permutation() 按字典序求全排列
  7. Using LINQ Group By and String.Join() / Aggregate() in Entity Framework 3.5
  8. 2014年度辛星html教程夏季版第四节
  9. 转: JavaScript函数式编程(二)
  10. 记一次erlang语言bug导致rabbitmq的队列没有消费者的问题
  11. nginx + tomcat 反向代理
  12. 【安富莱】【RL-TCPnet网络教程】第7章 RL-TCPnet网络协议栈移植(裸机)
  13. 关于微信小程序使用canvas生成图片,内容图片跨域的问题
  14. telerik reporting报表
  15. UVA 12171 Sculpture
  16. golang interface 转 string,int,float64
  17. 【ELK】4.spring boot 2.X集成ES spring-data-ES 进行CRUD操作 完整版+kibana管理ES的index操作
  18. CSS命名规范(规则)常用的CSS命名规则
  19. 2016 UESTC Training for Data Structures 题解
  20. java 包 和 物理目录 解惑

热门文章

  1. Codeforces 622F 「数学数论」「数学规律」
  2. python正则表达式介绍
  3. (medium)LeetCode 207.Course Schedule
  4. [POJ 2923] Relocation (动态规划 状态压缩)
  5. Flex 医疗行程图
  6. [Mongo] 简单的操作命令
  7. 关于java.lang.String理解中的一些难点
  8. 慕课网-安卓工程师初养成-3-6 Java中的逻辑运算符
  9. 第4章 awk编程
  10. PL/SQL 导入excel表格到oracle数据表