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 密码强度判断代码
Sep 05 Javascript
JavaScript(js)设置默认输入焦点(focus)
Dec 28 Javascript
纯JavaScript代码实现移动设备绘图解锁
Oct 16 Javascript
浅析Bootstrap组件之面板组件
May 04 Javascript
JavaScript中三个等号和两个等号的区别(== 和 ===)浅析
Sep 22 Javascript
JavaScript生成.xls文件的代码
Dec 22 Javascript
jquery滚动条插件slimScroll使用方法
Feb 09 Javascript
JavaScript实现分页效果
Mar 28 Javascript
Vue.js tab实现选项卡切换
May 16 Javascript
使用jQuery.Pin垂直滚动时固定导航
May 24 jQuery
Vue-cli3简单使用(图文步骤)
Apr 30 Javascript
vue 保留两位小数 不能直接用toFixed(2) 的解决
Aug 07 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解压文件代码实现php在线解压
2014/02/13 PHP
在WordPress中实现发送http请求的相关函数解析
2015/12/29 PHP
几个高效,简洁的字符处理函数
2007/04/12 Javascript
IE不出现Flash激活框的小发现的js实现方法
2007/09/07 Javascript
一款Jquery 分页插件的改造方法(服务器端分页)
2011/07/11 Javascript
往光标所在位置插入值的js代码
2013/09/22 Javascript
JS实现鼠标经过好友列表中的好友头像时显示资料卡的效果
2014/07/02 Javascript
JS小游戏之宇宙战机源码详解
2014/09/25 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
2016/08/23 Javascript
jQuery实现可展开折叠的导航效果示例
2016/09/12 Javascript
浅谈JS使用[ ]来访问对象属性
2016/09/21 Javascript
JavaScript 拖拽实例代码
2016/09/21 Javascript
Angular2平滑升级到Angular4的步骤详解
2017/03/29 Javascript
vue中使用localstorage来存储页面信息
2017/11/04 Javascript
vue的无缝滚动组件vue-seamless-scroll实例
2017/12/18 Javascript
AngularJS基于http请求实现下载php生成的excel文件功能示例
2018/01/23 Javascript
JS实现简单的文字无缝上下滚动功能示例
2019/06/22 Javascript
基于Node的Axure文件在线预览的实现代码
2019/08/28 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
2019/09/27 Javascript
WEB前端性能优化的7大手段详解
2020/02/04 Javascript
解决vue里a标签值解析变量,跳转页面,前面加默认域名端口的问题
2020/07/22 Javascript
vue设置全局访问接口API地址操作
2020/08/14 Javascript
Vue3 实现双盒子定位Overlay的示例
2020/12/22 Vue.js
Python异常学习笔记
2015/02/03 Python
python中如何进行连乘计算
2020/05/28 Python
利用Python实现朋友圈中的九宫格图片效果
2020/09/03 Python
印尼最大的网上书店:Gramedia.com
2018/09/13 全球购物
求职自荐信格式
2013/12/04 职场文书
路政管理毕业自荐书范文
2014/02/10 职场文书
吸烟检讨书2000字
2014/02/13 职场文书
初中生操行评语大全
2014/04/24 职场文书
工作业绩不及格检讨书
2014/10/28 职场文书
项目经理助理岗位职责
2015/04/13 职场文书
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python
解决mysql问题:由于找不到MSVCR120.dll,无法继续执行代码
2021/06/26 MySQL
TV动画《间谍过家家》公开PV
2022/03/20 日漫