javascript中的闭包个很让人头疼的概念。总结一下

闭包是指有权访问一个函数作用域中的变量的函数。创建闭包最常见的方式,是在一个函数内部创建另一个函数,用return返回出去。

使用闭包可能造成内存占用不足,尽量少使用。

先看几个例子:

 function foo(){
var a = 2; function bar(){
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // 2

bar函数就是一个闭包。调用foo()函数时,得到的是bar函数,赋值给baz。此时,baz就指向内部的bar函数。再调用baz函数,就是调用了内部的bar函数了。

  function foo() {
var num = 2;
function bar() {
alert(++num);
}
return bar;
}
var baz = foo();
9 baz(); //3
10 baz(); //4

这和上面的区别是,内部函数变成自加函数,就能说明一些东西了。两次调用,发现它自增,而不是输出相同的数字3,说明了baz函数执行后,num对象没有被销毁,还保存在内存中。

 

如果没有闭包,那么foo函数执行完后,num对象就要被销毁,但因为闭包的存在,bar函数要访问num对象,所以要把bar函数需要的资源(foo函数)保存在内存中,使其不被销毁。所以输出的是 3 和 4

 function foo() {
var num = 2;
function bar() {
alert(++num);
}
bar();
}
foo(); //3
foo(); //3

如果变成这样,那就没有闭包了(return没了)。无论调用几次都输出3,因为函数运行后就被销毁了,不会保存。

看这个例子:

   function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); //
  nAdd();
  result(); //

要说明的是,nAdd()为什么能在外面调用?有两点

1、没有用var ,是一个全局对象,但单有这个还不够。也不能直接在外面调用

2、f1函数必须先执行才能调用nAdd函数,调用了函数就有了闭包,外面就可以访问里面的全局对象或全局方法了。

看这个例子:

有个全局函数叫setTimeout,可以这样使用:

 function msg(){
console.log("Message");
}
setTimeout(msg,2000);

两秒后输出:Message

下面我们想给msg传递参数,需要让msg返回一个函数给setTimeout使用,如下:

 function msg(m){
return function() {
console.log("Message from: " + m);
}
}
setTimeout(msg("setTimeout"),2000);

两秒后输出:Message from: setTimeout

上面那个是正确版本,msg的参数t作为闭包的一部分绑定给了返回的函数,如果我们这样定义的话就是错误的:

 function msg(m){
return function(m) {
console.log("Message from: " + m);
}
}

因为返回了一个带参数“m”的函数,会在setTimeout执行的时候在当前上下文中查找一个叫“m”的变量,而并没有此变量,故得到一个非预期的输出如下:Message from: undefined

闭包可以解决一个最常见的循环调用的例子:一个ul,点击每个li,弹出它的索引值。

 var aLi = document.getElementsByTagName('li'); //假设有6个li
for(var i = 0; i < aLi.length; i++){
aLi[i].onclick = function(){
alert(i);
}
}

看起来好像对了,其实结果是:无论你点击哪一个li,弹出的都是6。这是因为for里面的匿名函数没有保存起来,加载网页的时候执行了,循环结束了。点击时,会去寻找变量i,这时循环结束,i是6。

用闭包可以把它保存起来:

 var aLi = document.getElementsByTagName('li');
for (var i = 0; i <= aLi.length; i++) {
aLi[i].onclick = (function(i){
return function(){
alert(i);
};
})(i);
}

当点击li时就是调用了闭包函数onclick,使得外部i变量不被销毁,达到目的。

这样也可以解决,通过闭包机制模仿块级作用域

   var aLi = document.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
(function(i){
aLi[i].onclick = function(){
alert(i);
}
})(i)
}

以上为学习总结,如有错误,望指正

javascript闭包学习例子的更多相关文章

  1. JavaScript闭包学习笔记

    此文都是大牛们关于闭包的观点,在此只是总结. 闭包应用的两种情况即可——函数作为返回值,函数作为参数传递. 1 深入理解javascript原型和闭包 判断一个变量是不是对象非常简单.值类型的类型判断 ...

  2. javascript 闭包学习

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  3. javascript闭包学习

    (function(){})()===>>>>函数会被立即执行function(){}是一个函数用括号包起来表示是函数表达式再加()表示函数自执行  如何理解闭包?1.定义和用 ...

  4. javascript 闭包理解例子

    function Jquery(){ this.name = 'ysr'; this.sex = 'man'; return { x: this, age : 26 } } var b = new J ...

  5. JavaScript 闭包的例子

    例子出自<<JavaScript权威指南>>, 加上个人的理解和总结, 欢迎交流! /********************************************* ...

  6. Javascript闭包学习(Closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  7. JavaScript学习总结(十六)——Javascript闭包(Closure)

    原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依 ...

  8. [转载]学习Javascript闭包(Closure)

    学习Javascript闭包(Closure)     源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...

  9. ife task0003学习笔记(三):JavaScript闭包

    一.this易错分析 在学习闭包的时候,有一个概念this很重要,关于this的理解,下面3种情况:this指向谁? fn.call(obj1); obj2.fn() fn() 答案是obj1 obj ...

随机推荐

  1. sublime text3使用小结

    一.下载 http://www.sublimetext.com/2   sublime text2下载页 http://www.sublimetext.com/3   sublime text3下载页 ...

  2. 安装vs2010,vs2015后,删除2015,导致vs2016打不开

    报错:Cannot evaluate the property expression "$([MSBuild]::ValueOrDefault('$(VCTargetsPath)','$(M ...

  3. javaWeb开发小工具--MyCommonUtils

    MyCommonUtils 参考一些资料,写了这个工具类.在这个工具类中,主要实现了2个方法: 1.生成随机的序列号 uuid(): 2.将Map中的数据封装到javaBean对象中toBean(Ma ...

  4. RestSharp简单扩展

    using RestSharp; using RestSharp.Deserializers; using RestSharp.Serializers; using System; using Sys ...

  5. I2C VHDL程序

    http://blog.sina.com.cn/s/blog_9bd80b7601012o9y.html library ieee ; use ieee.std_logic_1164.all ; us ...

  6. 搜索引擎 ElasticSearch 之 步步为营1 【环境搭建&初识ElasticSearch】

    1.下载ElasticSearch a.下载Java环境JDK:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloa ...

  7. testng+reportng,运行xml

    在看了http://seleniumcn.cn/read.php?tid=7960视频的Reportng后自己实验了下, 1.下载reportng-1.1.4.zip,解压后如下,把reportng- ...

  8. Android学习地址

    Google Android官方培训课程中文版http://hukai.me/android-training-course-in-chinese/

  9. C语言-数据类型

    数据类型 -基本数据类型 --char 字符型 --int  整型 --浮点型 ---float ---double -指针类型 --void* -空类型 -构架类型 --数组[] --结构体 str ...

  10. 多线程_先产后销_运行结果有BUG

    class Shop { public static void main(String[] args) { Things t=new Things(); Custom c=new Custom(t); ...