js函数4-闭包
2016-04-18 21:24
495 查看
js采用词法作用域,也就是说函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性叫做闭包。
实际上所有的js函数都可以叫做闭包,它们都是对象,它们都关联到作用域链,定义大多数函数时的作用域链在调用函数时依然有效,但这不影响闭包。当调用函数时闭包所指向的作用域链和定义函数时的作用域链不是同一个作用域链时,事情就变得非常微妙。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope(); //local scope在函数中定义了嵌套函数,作用域链上有三个对象(作用域链知识参考上一篇文章--作用域与作用域链)定义与调用也发生在checkscope的作用域中,所以打印出local scope比较好理解。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()(); //local scope在这个例子中,返回的是f 函数的定义,也就是说f 函数定义时在checkscope的作用域中,而调用发生在全局作用域下。但返回的仍然是local scope。事实上调用时用到的作用域链是函数定义的时候创建的,不管在何时何地执行f() 时依然是有效的,返回的f 就是一个闭包。它可以捕捉到局部变量(和参数),并一直保存下来。
关于闭包原理的解释,犀牛书第6版184页中有非常详细经典的解释。
多个嵌套函数(闭包)共享同一个作用域链:
function counter(){
var n = 0;
return{
count : function(){return n++},
reset : function(){n = 0}
};
}
var c = counter(), d = counter();
c.count(); // 0
d.count(); // 0
c.reset();
c.count(); // 0
d.count(); // 1两个嵌套函数会共享同一个作用域链,所以当c.reset()后再调用c.count(),打印出来的会是0.
但c和d之间不会互相影响,因为每调用一次counter()就会新建一个作用域链和一个新的私有变量n。
上面这种写法也是利用闭包进行私有变量封装的方法,只有返回的闭包可以直接操作私有变量,不可直接操作变量n。
实际上所有的js函数都可以叫做闭包,它们都是对象,它们都关联到作用域链,定义大多数函数时的作用域链在调用函数时依然有效,但这不影响闭包。当调用函数时闭包所指向的作用域链和定义函数时的作用域链不是同一个作用域链时,事情就变得非常微妙。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope(); //local scope在函数中定义了嵌套函数,作用域链上有三个对象(作用域链知识参考上一篇文章--作用域与作用域链)定义与调用也发生在checkscope的作用域中,所以打印出local scope比较好理解。
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()(); //local scope在这个例子中,返回的是f 函数的定义,也就是说f 函数定义时在checkscope的作用域中,而调用发生在全局作用域下。但返回的仍然是local scope。事实上调用时用到的作用域链是函数定义的时候创建的,不管在何时何地执行f() 时依然是有效的,返回的f 就是一个闭包。它可以捕捉到局部变量(和参数),并一直保存下来。
关于闭包原理的解释,犀牛书第6版184页中有非常详细经典的解释。
多个嵌套函数(闭包)共享同一个作用域链:
function counter(){
var n = 0;
return{
count : function(){return n++},
reset : function(){n = 0}
};
}
var c = counter(), d = counter();
c.count(); // 0
d.count(); // 0
c.reset();
c.count(); // 0
d.count(); // 1两个嵌套函数会共享同一个作用域链,所以当c.reset()后再调用c.count(),打印出来的会是0.
但c和d之间不会互相影响,因为每调用一次counter()就会新建一个作用域链和一个新的私有变量n。
上面这种写法也是利用闭包进行私有变量封装的方法,只有返回的闭包可以直接操作私有变量,不可直接操作变量n。
相关文章推荐
- Extjs4.0 最新最全视频教程
- 深入理解PHP之匿名函数
- Javascript中toFixed方法的改进
- 5个常见可用性错误和解决方案
- 最后一次说说闭包
- js数组实现图片轮播
- js可突破windows弹退效果代码
- Ruby中使用Block、Proc、lambda实现闭包
- JSP脚本漏洞面面观
- 使用BAT一句话命令实现快速合并JS、CSS
- LUA中的闭包(closure)浅析
- Lua中的闭包学习笔记
- js显示当前星期的起止日期的脚本
- C#中函数的创建和闭包的理解
- 爆炸式的JS圆形浮动菜单特效代码
- js select常用操作控制代码
- JS实现不使用图片仿Windows右键菜单效果代码
- 从jsp发送动态图像
- 原生js结合html5制作小飞龙的简易跳球
- js 页面模块自由拖动实例