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 相关文章推荐
javascript下操作css的float属性的特殊写法
Aug 22 Javascript
Javascript var变量隐式声明方法
Oct 19 Javascript
jQuery中detach()方法用法实例
Dec 25 Javascript
跟我学习javascript的Date对象
Nov 19 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
May 18 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
Mar 04 Javascript
angularjs select 赋值 ng-options配置方法
Feb 28 Javascript
vue-cli在 history模式下的配置详解
Nov 26 Javascript
js实现鼠标点击页面弹出自定义文字效果
Dec 24 Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
Apr 25 Javascript
Vue 如何使用props、emit实现自定义双向绑定的实现
Jun 05 Javascript
JS实现4位随机验证码
Oct 19 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中\r \r\n \t的区别示例介绍
2014/02/08 PHP
php对数组排序代码分享
2014/02/24 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
PHP实现获取某个月份周次信息的方法
2015/08/11 PHP
YII动态模型(动态表名)支持分析
2016/03/29 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
基于PHP实现邮箱验证激活过程详解
2020/10/28 PHP
微博@符号的用户名提示效果。(想@到谁?)
2010/11/05 Javascript
悬浮数字的实现案例
2014/02/19 Javascript
jQuery中多个元素的Hover事件解决方案
2014/06/12 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
在其他地方你学不到的jQuery小贴士和技巧(欢迎收藏)
2016/01/20 Javascript
js中实现字符串和数组的相互转化详解
2016/01/24 Javascript
JS变量中有var定义和无var定义的区别以及es6中let命令和const命令
2017/02/19 Javascript
前端面试知识点目录一览
2019/04/15 Javascript
JS实现分页导航效果
2020/02/19 Javascript
在Uni中使用Vue的EventBus总线机制操作
2020/07/31 Javascript
Python中绑定与未绑定的类方法用法分析
2016/04/29 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
Python 快速实现CLI 应用程序的脚手架
2017/12/05 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
selenium+python实现基本自动化测试的示例代码
2021/01/27 Python
瑞贝卡·泰勒官方网站:Rebecca Taylor
2016/09/24 全球购物
瑞典快乐袜子:Happy Socks
2018/02/16 全球购物
Derek Rose官网:英国高档睡衣、家居服和内衣品牌
2020/01/18 全球购物
PyQt 如何创建自定义QWidget
2021/03/24 Python
高校辅导员推荐信范文
2013/12/25 职场文书
迟到检讨书500字
2014/02/05 职场文书
药品促销活动方案
2014/02/14 职场文书
大专生自荐书范文
2014/06/22 职场文书
夫妻分居协议书范本(有子女版)
2014/11/01 职场文书
党员活动总结
2015/02/04 职场文书
2015小学教育教学工作总结
2015/07/21 职场文书
公司费用报销管理制度
2015/08/04 职场文书
Pytorch GPU内存占用很高,但是利用率很低如何解决
2021/06/01 Python
Redis中一个String类型引发的惨案
2021/07/25 Redis