for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}

——上面这段代码,如果对JavaScript闭包没有概念的话,将是一头雾水。 by 羊大葱 于2016年10月25日

几种典型闭包写法

1、最基础写法

function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 —— 麻麻快看,这就是闭包的效果。

2、较为变种写法

function foo() {
var a = 2;
function baz() {
console.log( a ); //
}
bar( baz );
}
function bar(fn) {
fn(); // 妈妈快看呀,这就是闭包!
}

2.1第二种写法简明写法(传递函数间接的传递)

var fn;
function foo() {
var a = 2;
function baz() {
console.log( a );
}
fn = baz; // 将baz 分配给全局变量
}
function bar() {
fn(); // 妈妈快看呀,这就是闭包!
}

3.直接外面函数引用

function wait(message) {
setTimeout( function timer() {
console.log( message );
}, 1000 );
}
wait( "Hello, closure!" );

将一个内部函数(名为timer)传递给setTimeout(..)。timer 具有涵盖wait(..) 作用域的闭包,因此还保有对变量message 的引用。wait(..) 执行1000 毫秒后,它的内部作用域并不会消失,timer 函数依然保有wait(..)作用域的闭包。

3.1 直接外面函数引用常见用法

function setupBot(name, selector) {
$( selector ).click( function activator() {
console.log( "Activating: " + name );
} );
}
setupBot( "Closure Bot 1", "#bot_1" );
setupBot( "Closure Bot 2", "#bot_2" );

如果你很熟悉jQuery(或者其他能说明这个问题的JavaScript 框架),可以思考3.1的代码。

本质上无论何时何地如果将函数(访问它们各自的词法作用域)当作第一级的值类型并到处传递,你就会看到闭包在这些函数中的应用。在定时器、事件监听器、Ajax 请求、跨窗口通信、Web Workers 或者任何其他的异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包!

回到文章一开始的代码

为什么一直输出的是6呢?

由于很多开发者对闭包的概念认识得并不是很清楚,因此当循环内部包含函数定义时,代码格式检查器经常发出警告!

第一、在循环外部函数定义
function t1(a){console.log(a);};
for(var i=1; i<=5; i++){
setTimeout(t1(i),i*1000);
}
//----------------------------------------------------------
第二、直接在循环内部包含函数定义
for (var i=1; i<=5; i++) {
setTimeout( function timer() { console.log( i ); }, i*1000 );
}

  上面两种写法,第一种输出时1、2、3、4、5;第二种写法输入为6,6,6,6,6。

上图是我在两种情况下,当迭代循环到5的时候打出‘d5’,以探究两种情况的执行顺序。很显然,第一种形成闭包情况下,是等迭代全部执行完才开始执行setTimeout();而第二种非闭包情况下是直接每个循环执行的!

最新文章

  1. MySQL对时间戳的转换处理
  2. window 安装grunt
  3. [iOS Xcode注释插件]
  4. web页面隐藏鼠标
  5. busybox rootfs 启动脚本分析(一)
  6. Visual Studio 2015和ASP.NET 5中可用的前端开发工具集
  7. 去掉inline-block元素间隙的几种方法
  8. Redis: OOM command not allowed when used memory &gt; ‘maxmemory
  9. UDP协议疑难杂症全景解析
  10. tips [终端]
  11. HID Boot device.
  12. Python 正则表达试
  13. 精致的外观Request
  14. AngularJS操作DOM——angular.element
  15. curl命令用于模拟http浏览器发起动作
  16. SQL开窗函数
  17. angularjs自定义filter
  18. Bugku-CTF之flag.php(点了login咋没反应)
  19. ACM__并查集
  20. 刚创建的maven项目,pom.xml的第一行就报错

热门文章

  1. primefaces 查询 点击按钮 加载 动画 ajax loader
  2. 自学 Java 怎么入门
  3. 11月1日上午PHP批量删除
  4. Daily Build
  5. 在 Github 上找「好东西」的方法
  6. R的卸载和更新安装
  7. Excel 自动更正
  8. [Machine Learning &amp; Algorithm] 决策树与迭代决策树(GBDT)
  9. [Search Engine] 搜索引擎分类和基础架构概述
  10. PHP数据采集curl常用的5个例子