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 ...
随机推荐
- Web系统大规模并发——电商秒杀与抢购 【转】
电商的秒杀和抢购,对我们来说,都不是一个陌生的东西.然而,从技术的角度来说,这对于Web系统是一个巨大的考验.当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要.这次我们 ...
- Java printf
- Oracle学习笔记2
主键 create table userinfo_test( userid number(3,0), username varchar2(20), pwd varchar2(20), constrai ...
- android中布局文件中 layout_weight 的属性详解
在不同的情况下,layout_weight属性作用是不同的.主要有两种属性: 1.当布局中的控件的尺寸(宽和高)都有指定时,它所表示的该控件在父容器中的比重,及它在父容器中所占的比例,数值越大,比重越 ...
- 彻底弄懂js循环中的闭包问题
来源:http://www.108js.com/article/article1/10177.html?id=899 第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然 ...
- 命令行中mysql乱码问题
1.现象 在命令行中,执行sql语句如果包含中问题,提示“ Data too long for column '列名' at row 1” 或者在命令行中查询出的结果中,中文乱码 2.分析 ...
- 【转】java调用webservice
互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的Web应用中显示,下面就以获取天气预报数据和查询国内手机号码归属地为 ...
- testng参数化(提供测试数据)【转】
testng提供测试数据的两个注释:@DataProvide和@Parameter 一.通过testng.xml中设置参数 (实际上testng.xml只是一个名字,可以起任何一个名字,只要是.x ...
- hdoj 1022 Train Problem I
#include<stdio.h> int main() { int n,i,j,k; ],]; ]; while(scanf("%d %s %s",&n,in ...
- 微信公众号 扫码支付 模式二 demo
扫码支付 本文附有代码,在下方,如果不熟悉场景的可以看看下面的场景介绍 场景介绍 官网介绍地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?ch ...