javascript闭包学习例子
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闭包学习例子的更多相关文章
- JavaScript闭包学习笔记
此文都是大牛们关于闭包的观点,在此只是总结. 闭包应用的两种情况即可——函数作为返回值,函数作为参数传递. 1 深入理解javascript原型和闭包 判断一个变量是不是对象非常简单.值类型的类型判断 ...
- javascript 闭包学习
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...
- javascript闭包学习
(function(){})()===>>>>函数会被立即执行function(){}是一个函数用括号包起来表示是函数表达式再加()表示函数自执行 如何理解闭包?1.定义和用 ...
- javascript 闭包理解例子
function Jquery(){ this.name = 'ysr'; this.sex = 'man'; return { x: this, age : 26 } } var b = new J ...
- JavaScript 闭包的例子
例子出自<<JavaScript权威指南>>, 加上个人的理解和总结, 欢迎交流! /********************************************* ...
- Javascript闭包学习(Closure)
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...
- JavaScript学习总结(十六)——Javascript闭包(Closure)
原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依 ...
- [转载]学习Javascript闭包(Closure)
学习Javascript闭包(Closure) 源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...
- ife task0003学习笔记(三):JavaScript闭包
一.this易错分析 在学习闭包的时候,有一个概念this很重要,关于this的理解,下面3种情况:this指向谁? fn.call(obj1); obj2.fn() fn() 答案是obj1 obj ...
随机推荐
- C#的对象赋值
例如 Class A { int x = 0; int y = 0; } public void test() { A test1 = new A( ); ...
- IOS中CoreData浅析
CoreData简介: 什么是CoreData? Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中, ...
- ArcGIS百米网格自动生成
最近需要用百米网格进行空间叠加分析,首先得自动生成百米网格数据.经过查找,发现ARCgis可以自动生成网格.方法如下 2.创建格网(Creat Fishnet).需要用到ArcGIS的ArcToolb ...
- [java基础知识]java安装步骤
jre: java运行环境. jre = java虚拟机 + 核心类库(辅助java虚拟机运行的文件).如果只是运行java程序,只需要安装jre. jdk: java开发工具集 jd ...
- Java中HashMap等的实现要点浅析
@南柯梦博客中的系列文章对Jdk中常用容器类ArrayList.LinkedList.HashMap.HashSet等的实现原理以代码注释的方式给予了说明(详见http://www.cnblogs.c ...
- 控制反转容器& 依赖注入模式 ---读感。
几个web框架 : sprint Avalon PicoContainerclass MovieLister MovieFinder finder = ServiceLocator.movieFind ...
- iOS 里面 NSTimer 防止 循环引用
使用NSTimer的类 #import "TBTimerTestObject.h" #import "TBWeakTimerTarget.h" @interfa ...
- Linux之RPM安装软件
源码包 (可以看到源代码) 脚本安装包(写好的xsheel一键安装.本质还是源码包和二进制包) 二进制包(RPM包.系统默认包) 包管理系统简单,通过命令就可以安装.卸载 ...
- phoenix 开发API系列(三)phoenix api 结合数据库
概述 介绍了 api 的各种写法之后,下面介绍构建 api 时与数据库连接的方式. 注 下面使用的工程的完整代码已经公开在: http://git.oschina.net/wangyubin/phoe ...
- seajs 源码阅读笔记
代码概览 src目录文件列表如下: 代码以模块化的方式来组织,构建的时候会合并为一个js文件(sea.js 或 sea-debug.js),其中,intro.js和 outro.js 分别是这个js文 ...