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索引在使用中的一些困惑
Oct 24 Javascript
javascript使用数组的push方法完成快速排序
Sep 15 Javascript
javascript封装 Cookie 应用接口
Aug 07 Javascript
Javascript中字符串相关常用的使用方法总结
Mar 13 Javascript
微信小程序后台解密用户数据实例详解
Jun 28 Javascript
vue 挂载路由到头部导航的方法
Nov 13 Javascript
JQuery选中select组件被选中的值方法
Mar 08 jQuery
JS 事件机制完整示例分析
Jan 15 Javascript
Vue动态加载图片在跨域时无法显示的问题及解决方法
Mar 10 Javascript
详谈vue中router-link和传统a链接的区别
Jul 22 Javascript
JavaScript本地储存:localStorage、sessionStorage、cookie的使用
Oct 13 Javascript
Vue3+elementui plus创建项目的方法
Dec 01 Vue.js
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多用户计数器代码
2007/03/11 PHP
使用PHP实现密保卡功能实现代码&amp;lt;打包下载直接运行&amp;gt;
2011/10/09 PHP
PHP版微信公众平台红包API
2015/04/02 PHP
jQuery Ajax使用 全解析
2010/12/15 Javascript
jQuery实现列表自动循环滚动鼠标悬停时停止滚动
2013/09/06 Javascript
jQuery学习笔记之jQuery.fn.init()的参数分析
2014/06/09 Javascript
使用jQuery jqPlot插件绘制柱状图
2014/12/18 Javascript
JavaScript的内存释放问题详解
2015/01/21 Javascript
JavaScript脚本判断蜘蛛来源的方法
2015/09/22 Javascript
JS基于ocanvas插件实现的简单画板效果代码(附demo源码下载)
2016/04/05 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
2016/06/24 Javascript
jquery表单验证插件validation使用方法详解
2017/01/20 Javascript
javascript实现数据双向绑定的三种方式小结
2017/03/09 Javascript
jQuery实现简单的滑动导航代码(移动端)
2017/05/22 jQuery
基于JS代码实现简单易用的倒计时 x 天 x 时 x 分 x 秒效果
2017/07/13 Javascript
Vue AST源码解析第一篇
2017/07/19 Javascript
提升页面加载速度的插件InstantClick
2017/09/12 Javascript
jQuery 利用ztree实现树形表格的实例代码
2017/09/27 jQuery
微信小程序中遇到的iOS兼容性问题小结
2018/11/14 Javascript
jQuery插件实现非常实用的tab栏切换功能【案例】
2019/02/18 jQuery
JS中注入eval, Function等系统函数截获动态代码
2019/04/03 Javascript
javascript实现超好看的3D烟花特效
2020/01/01 Javascript
Python translator使用实例
2008/09/06 Python
win7 下搭建sublime的python开发环境的配置方法
2014/06/18 Python
python使用Berkeley DB数据库实例
2014/09/26 Python
pandas值替换方法
2018/07/10 Python
学生信息管理系统python版
2018/10/17 Python
Python基于OpenCV实现人脸检测并保存
2019/07/23 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
C#里面如何倒序排列一个数组的元素?
2013/06/21 面试题
关于元旦的广播稿
2014/02/16 职场文书
搞笑婚礼主持词
2014/03/13 职场文书
初中地理教学反思
2016/02/19 职场文书
56句经典英文座右铭
2019/08/09 职场文书
MySQL数据迁移相关总结
2021/04/29 MySQL
解析目标检测之IoU
2021/06/26 Python