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的一个拖拽到指定区域内的效果
Sep 21 Javascript
javascript 判断中文字符长度的函数代码
Aug 27 Javascript
jQuery 关于伪类选择符的使用说明
Apr 24 Javascript
JavaScript中的单引号和双引号报错的解决方法
Sep 01 Javascript
jquery移动点击的项目到列表最顶端的方法
Jun 24 Javascript
js实现仿MSN带关闭功能的右下角弹窗代码
Sep 04 Javascript
Bootstrap精简教程
Nov 27 Javascript
jquery图片放大镜效果
Jun 23 jQuery
Vue Transition实现类原生组件跳转过渡动画的示例
Aug 19 Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
Sep 11 Javascript
基于Node.js实现压缩和解压缩的方法
Feb 13 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
Mar 01 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 Memcached应用实现代码
2010/02/08 PHP
php结合表单实现一些简单功能的例子
2011/06/04 PHP
php学习笔记之 函数声明
2011/06/09 PHP
php中hashtable实现示例分享
2014/02/13 PHP
十大使用PHP框架的理由
2015/09/26 PHP
php去除二维数组的重复项方法
2015/11/03 PHP
php中Ioc(控制反转)和Di(依赖注入)
2017/05/07 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
JavaScript异步回调的Promise模式封装实例
2014/06/07 Javascript
js实现拖拽功能
2017/03/01 Javascript
JS实现微信里判断页面是否被分享成功的方法
2017/06/06 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
详解jquery和vue对比
2019/04/16 jQuery
如何从头实现一个node.js的koa框架
2019/06/17 Javascript
vue+element实现图片上传及裁剪功能
2020/06/29 Javascript
原生小程序封装跑马灯效果
2020/10/21 Javascript
Vant+postcss-pxtorem 实现浏览器适配功能
2021/02/05 Javascript
python共享引用(多个变量引用)示例代码
2013/12/04 Python
操作Windows注册表的简单的Python程序制作教程
2015/04/07 Python
浅谈numpy中linspace的用法 (等差数列创建函数)
2017/06/07 Python
python+numpy+matplotalib实现梯度下降法
2018/08/31 Python
python3.4控制用户输入与输出的方法
2018/10/17 Python
对python 读取线的shp文件实例详解
2018/12/22 Python
python 缺失值处理的方法(Imputation)
2019/07/02 Python
python json.dumps中文乱码问题解决
2020/04/01 Python
python 使用raw socket进行TCP SYN扫描实例
2020/05/05 Python
pycharm 使用anaconda为默认环境的操作
2021/02/05 Python
网站性能延迟加载图像的五种技巧(小结)
2020/08/13 HTML / CSS
美国领先的男士和女士内衣购物网站:Freshpair
2019/02/25 全球购物
应届大学生求职的自我评价
2013/11/17 职场文书
销售主管的自我评价分享
2014/01/03 职场文书
公积金转移接收函
2014/01/11 职场文书
2014年公务员退休工资改革方案
2014/10/01 职场文书
告知书格式
2015/07/01 职场文书
微信小程序APP页面的之间的相互传递参数以及自定义组件
2022/04/19 Javascript
JavaScript实现九宫格拖拽效果
2022/06/28 Javascript