javascript 闭包详解

 更新时间:2015年07月02日 12:09:23   投稿:hebedich  
闭包:是指有权访问另外一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另外一个函数。在javascript中没有块级作用域,一般为了给某个函数申明一些只有该函数才能使用的局部变量时,我们就会用到闭包,我们来详细探讨下

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

问:闭包是什么?
答:闭包是指在 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 

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

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

相关文章

  • js使用cookie实现记住用户名功能示例

    js使用cookie实现记住用户名功能示例

    这篇文章主要介绍了js使用cookie实现记住用户名功能,涉及javascript操作cookie读写及删除实现用户名的保存功能,需要的朋友可以参考下
    2019-06-06
  • 小程序中手机号识别的示例

    小程序中手机号识别的示例

    这篇文章主要介绍了小程序中手机号识别的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 纯javascript实现图片延时加载方法

    纯javascript实现图片延时加载方法

    看到一篇博客说土豆网的图片是延迟加载的。原理是这样:页面可见区域以下的图片先不加载,等到用户向下滚动到图片位置时,再进行加载。这样做的好处是当页面有好几屏内容时,这样我们就可以只加载用户需要看的图片,减少服务器向用户浏览器发送图片文件所产生的负荷。
    2015-08-08
  • Javascript字符串常用方法详解

    Javascript字符串常用方法详解

    这篇文章主要介绍了Javascript字符串常用方法详解的相关资料,在平时工作中经常会用到的,非常不错,需要的朋友可以参考下
    2016-07-07
  • 深入理解Javascript中this的作用域

    深入理解Javascript中this的作用域

    这篇文章主要介绍了深入理解Javascript中this的作用域,本文用大量例子来深入探讨this的作用域,需要的朋友可以参考下
    2014-08-08
  • 基于JS实现9种不同的面包屑和分布式多步骤导航效果

    基于JS实现9种不同的面包屑和分布式多步骤导航效果

    本文是小编给大家分享的基于js实现的9种不同风格的面包屑和分布式多步骤导航效果,非常不错,具有参考借鉴价值,需要的朋友参考下
    2017-02-02
  • js实现对ajax请求面向对象的封装

    js实现对ajax请求面向对象的封装

    这篇文章主要介绍了js实现对ajax请求面向对象的封装的相关资料,需要的朋友可以参考下
    2016-01-01
  • js的函数的按值传递参数(实例讲解)

    js的函数的按值传递参数(实例讲解)

    下面小编就为大家分享一篇js的函数的按值传递参数的实例,具有很好的参考价值,一起跟随小编过来看看吧,希望对大家有所帮助
    2017-11-11
  • 利用WebBrowser彻底解决Web打印问题(包括后台打印)

    利用WebBrowser彻底解决Web打印问题(包括后台打印)

    BS架构下的打印大家是怎么解决的呢,我最近作了一个项目正好负责这一块,不仅要求打印页面的特定部分,还要求有后台的批量打印,在网上查了一些资料,最后终于解决了。
    2009-06-06
  • 关于include标签导致js路径找不到的问题分析及解决

    关于include标签导致js路径找不到的问题分析及解决

    本文为大家详细介绍下关于使用jsp:include标签及<%@ include标签时要注意的事项以及实测发现问题并解决问题的全过程,感兴趣的各位可以参考下哈,希望对大家有所帮助
    2013-07-07

最新评论