Javascript 中的闭包和引用
2015-09-10 17:06
656 查看
Javascript中一个最重要的特性就是闭包的使用。因为闭包的使用,当前作用域总可以访问外部的作用域。因为
Javascript没有块级作用域,只有函数作用域,所以闭包的使用与函数是紧密相关的。
模拟私有变量
function Counter(start) { var count = start; return { increment: function() { count++; }, get: function() { return count; } } } var foo = Counter(4); foo.increment(); foo.get(); // 5
这里
Counter返回两个闭包:函数
increment和
get。这两个函数一直保持着对
Counter作用域的访问,因此它们能一直访问到定义在
Counter作用域的变量
count。
私有变量的工作机制
由于Javascript不可以对作用域赋值和引用,所以在上例中,是没有办法在外部直接访问内部私有变量
count。唯一的方法就是通过定义闭包来访问。
var foo = new Counter(4); foo.hack = function() { count = 1337; };
上面的代码不会改变
Counter作用域内的
count变量值,因为
hack没有在
Counter内定义。上面这段代码只会创建或者覆盖全局变量
count。
循环内的闭包
一个最容易犯的错误就是在循环内使用闭包。for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }
上面这段代码不会输出0到9,而是连续输出10次10。
上面的匿名会一直保持一个对变量
i的引用。当调用
console.log函数开始输出时,这是循环已经结束,而变量
i已经为10了。
为了避免上面的错误发生,我们需要在每次循环时为变量
i值创建一个拷贝。
避免引用错误
为了复制循环中变量的值,最好的方式是在外层加一个匿名的立刻执行函数。for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }
这个外部的匿名函数接收循环变量
i作为第一个参数,并将其值拷贝至它自身的参数
e。
外部的匿名函数将参数
e再传递给
setTimeout,因此
setTimeout有了指向参数
e的引用。而且这个参数
e的值不会因为外部的循环改变而改变。
还有另外一个方法可以实现同样的效果,就是在
setTimeout内的匿名函数中再返回一个匿名函数:
for(var i = 0; i < 10; i++) { setTimeout((function(e) { return function() { console.log(e); } })(i), 1000) }
此外,通过
bind方法也可以实现。
for(var i = 0; i < 10; i++) { setTimeout(console.log.bind(console, i), 1000); }
地址:http://bonsaiden.github.io/JavaScript-Garden/#function.closures
相关文章推荐
- js取url的参数
- 13个JavaScript图表图形绘制插件
- JS重定向跳转代码
- js获取表单文本框中的值
- js闭包的用途详解
- JS浏览器类型推断方法
- 深入浅出javascript闭包的用途和几种写法
- js 40 个技巧
- JS有用函数
- js常用方法
- javascript入门系列演示·三种弹出对话框的用法实例
- js中for in 和 for each in的用法和区别
- 【JS】识别浏览器版本及操作平台
- javascript运算符
- js window.onload 应用 addEventListener讲解
- css与javascript跨浏览器兼容性总结
- javascript字符串
- JS 之DOM对象(1)
- js操作DOM常用方法
- [AngualrJS + Webpack] Production Source Maps