javascript 闭包详解


Posted in Javascript onJuly 02, 2015

看了一下网上闭包的概念及文章,对于这个问题,自己做一个梳理吧。

问:闭包是什么?
答:闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

这个是我自身第一次碰到闭包的问题

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>闭包循环问题</title>
<style type="text/css">
p {background:#ccc; width: 300px; height: 100px;}
</style>
</head> 
<body> 
<p id="p0">段落0</p> 
<p id="p1">段落1</p> 
<p id="p2">段落2</p> 
<p id="p3">段落3</p> 
<p id="p4">段落4</p> 
<script type="text/javascript">
for( var i=0; i<5; i++ ) { 
document.getElementById("p"+i).onclick=function() { 
alert(i); //访问了父函数的变量i, 闭包 
};
};
</script> 
</body> 
</html>

如果你以前没这么用过的话,估计也会认为单击某个段落就会弹出这个段落相应的编号0,1,2,3,4。但实际上是都是弹出5;

对于这个问题网上已经有很多讨论的博客了,他们给出了很多方法去实现弹出对应的编号。

解决方法1:将变量i保存在对应的段落的某个属性上

var pAry = document.getElementsByTagName("p"); 
for( var i=0; i< 5; i++ ) { 
pAry[i].no = i; 
pAry[i].onclick = function() { 
alert(this.no); 
} 
};

解决方法2:加一层闭包,i 以函数参数形式传递给内层函数

var pAry = document.getElementsByTagName("p"); 
for( var i=0; i< 5; i++ ) { 
pAry[i].no = i; 
pAry[i].onclick = function() { 
alert(this.no); 
} 
};

对于这个产生的闭包问题,网上的说法是“变量i是以指针或者变量地址方式保存在函数中”;好吧,都和指针扯上关系了。。。。那就再探索一下吧。

探索1,返回的都是10而不是而是

(function test() { 
var temp =10; 
for(var i=0; i< 5; i++ ){ 
document.getElementById("p"+i).onclick=function() { 
alert(temp); //访问了父函数的变量temp, 闭包 
}
};
temp=20;
})();

探索2,返回一次10,接下去返回的都是20

(function test() { 
var temp =10; 
for( var i=0; i< 5; i++ ) { 
document.getElementById("p"+i).onclick=function() { 
alert(temp); //访问了父函数的变量i, 闭包 
}
if(i===1){
alert(temp);
}
};
temp=20;
})();

由探索的1、2,可以得出结论:函数内部访问了与函数同级的变量,那么该变量是常驻内存的。访问该变量实质上是访问的是变量的地址;

接着,又看了一篇关于“JS闭包中的this对象”的文章,继续来讨论一下,this这个问题吧。

// js闭包this对象1
var name = 'The Window';
var object = {
  name : 'My Object',
  getNameFunc1 : function(){
    // return this.name;
    console.log(this);//object
    return function(){//闭包,访问的便是全局变量的了,this指windows
     console.log(this);//windows
     return this.name; //The Window
    }
  },
  getNameFunc2 : function(){
     return this.name;//访问的是object
  },
  aa:function(){
   alert(22);
  }
};
alert(object.getNameFunc1()());//弹出“The Window”

问: 那么为什么匿名函数没有取得其包含作用域的this对象呢?
答:每个函数在被调用时都会自动获取两个特殊变量:this 和 arguments。 内部函数在搜索这两个变量时,指挥搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。
不过通过下面的代码可以做到这一点(直接访问外部函数中的变量):

// js闭包this对象2
var name = 'The Window';
var object = {
  name : 'My Object',
  getNameFunc : function(){
   var that = this;
   console.log(this);//输出的是object
   return function(){
    console.log(this);//输出的仍然是Windows
    return that.name;
   };
  }
};
alert(object.getNameFunc()());//弹出“My Object”

不同之处在于把this对象赋给了一个that变量,即使在函数返回之后,that也仍然引用这object,所以会返回object。
写了那么多闭包的东西,那也顺便再说一下闭包有神马用处吧;不然,一直捣乱那闭包可真是一个不好的家伙呢。

看这样一典型的闭包的例子:

function A(){
 var a=1;
 function B(){
  return a;
 }; 
 return B;
};

var C=A();//C取得A的子作用域B的访问接口
console.log(C());//1 C能访问到B的父级作用域中的变量a

只要其他作用域能取到子作用域的访问接口,那么其他作用域就有方法访问该子作用域父级作用域的变量了。这样的话,如果以后需要访问某个函数里面的值得时候,就大大的有用咯。

这些上面的很多代码其实也都是网上找的,我也只是把自己理解的,看的过程总结一下吧。

Javascript 相关文章推荐
jquery 如何动态添加、删除class样式方法介绍
Nov 07 Javascript
Android中资源文件(非代码部分)的使用概览
Dec 18 Javascript
左右悬浮可分组的网站QQ在线客服代码(可谓经典)
Dec 21 Javascript
Jquery和JS用外部变量获取Ajax返回的参数值的方法实例(超简单)
Jun 17 Javascript
javascript实现的元素拖动函数宿主为浏览器
Jul 21 Javascript
jQuery.Callbacks()回调函数队列用法详解
Jun 14 Javascript
js鼠标单击和双击事件冲突问题的快速解决方法
Jul 11 Javascript
浅谈Angular的$q, defer, promise
Dec 20 Javascript
jquery uploadify如何取消已上传成功文件
Feb 08 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
Sep 07 Javascript
使用ngrok+express解决本地环境中微信接口调试问题
Feb 26 Javascript
vue内置指令详解
Apr 03 Javascript
JavaScript实现点击自动选择TextArea文本的方法
Jul 02 #Javascript
浅谈Javascript线程及定时机制
Jul 02 #Javascript
JavaScript获得url查询参数的方法
Jul 02 #Javascript
js跨域请求的5中解决方式
Jul 02 #Javascript
JS实现从连接中获取youtube的key实例
Jul 02 #Javascript
由ReactJS的Hello world说开来
Jul 02 #Javascript
深入理解JavaScript的React框架的原理
Jul 02 #Javascript
You might like
PHP 最大运行时间 max_execution_time修改方法
2010/03/08 PHP
PHP学习 变量使用总结
2011/03/24 PHP
yii框架源码分析之创建controller代码
2011/06/28 PHP
使用php检测用户当前使用的浏览器是否为IE浏览器
2013/12/03 PHP
叫你如何修改Nginx与PHP的文件上传大小限制
2014/09/10 PHP
php 模拟 asp.net webFrom 按钮提交事件实例
2014/10/13 PHP
Thinkphp通过一个入口文件如何区分移动端和PC端
2017/04/18 PHP
深入理解PHP中mt_rand()随机数的安全
2017/10/12 PHP
PHP微信开发之微信录音临时转永久存储
2018/01/26 PHP
JS(jQuery)实现聊天接收到消息语言自动提醒功能详解【提示“您有新的消息请注意查收”】
2019/04/16 PHP
PHP获取真实IP及IP模拟方法解析
2020/11/24 PHP
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
JS 精确统计网站访问量的实例代码
2013/07/05 Javascript
js实现文本框中焦点在最后位置
2014/03/04 Javascript
移动端jQuery修正Web页面滑动时div问题的两则实例
2016/05/30 Javascript
详解webpack3如何正确引用并使用jQuery库
2017/08/26 jQuery
JavaScript 异步调用
2017/10/25 Javascript
vue 录制视频并压缩视频文件的方法
2018/07/27 Javascript
JS计算斐波拉切代码实例
2019/09/12 Javascript
javascript设计模式 ? 模板方法模式原理与用法实例分析
2020/04/23 Javascript
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
python实现dict版图遍历示例
2014/02/19 Python
python数据结构树和二叉树简介
2014/04/29 Python
python使用MySQLdb访问mysql数据库的方法
2015/08/03 Python
python语言使用技巧分享
2016/05/31 Python
pytorch AvgPool2d函数使用详解
2020/01/03 Python
python求numpy中array按列非零元素的平均值案例
2020/06/08 Python
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
英国时尚和家居用品零售商:Matalan
2021/02/28 全球购物
标准导师推荐信(医学类)
2013/10/28 职场文书
安全环保标语
2014/06/09 职场文书
个人主要事迹材料
2014/08/26 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
首都博物馆观后感
2015/06/05 职场文书
幼儿园教师管理制度
2015/08/05 职场文书
Python可变集合和不可变集合的构造方法大全
2021/12/06 Python