对闭包的理解

什么是闭包?

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

举个例子

function foo() {

   var a = 2; 

   function bar() { 

        console.log( a );//baz()的词法作用域能够访问foo()的内部作用域,即能访问到变量a

    } 

     return bar; 

} 

var baz = foo(); 

baz(); // 2 —— 朋友,这就是闭包的效果

当执行完var baz=foo();时,此时的 baz的值即为bar函数,即( function bar() { console.log( a ); } )此时baz函数在自己所定义的词法作用域以外的地方执行,这是一个典型的闭包

此处的return并不是必须的,只是为了外面可以访问到这个 bar 函数。无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。如

function foo() {
var a = 2;
function baz() {
console.log( a ); // 2
}
bar( baz );
}
function bar(fn) {
fn(); //这也是闭包!
}

把内部函数 baz 传递给 bar,当调用这个内部函数时(现在叫作 fn),它涵盖的 foo() 内部 作用域的闭包就可以观察到了,因为它能够访问 a。

也可以间接的访问传递函数

var fn;
function foo() {
var a = 2;
function baz() {
console.log( a );
}
fn = baz; // 将 baz 分配给全局变量
}
function bar() {
fn(); // 闭包!
}
foo();
bar(); // 2

无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用 域的引用,无论在何处执行这个函数都会使用闭包。

常见的闭包例子

可能你没有意识到,当你已经多次使用过闭包,如下例

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

以及我们经常使用的jQuery

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

在定时器、事件监听器、 Ajax 请求、跨窗口通信、Web Workers 或者任何其他的异步(或者同步)任务中,只要使 用了回调函数,实际上就是在使用闭包!

闭包的优缺点

如果我们想达到函数外部能访问内部变量的时候,我们就可以使用闭包,但是闭包会导致变量不会被垃圾回收机制所清除,会大量消耗内存。原因如下

以举的第一个例子为例

function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 —— 朋友,这就是闭包的

在 foo() 执行后,通常会期待 foo() 的整个内部作用域都被销毁,由于看上去 foo() 的内容不会再被使用,故引擎的垃圾回收机制会来释放不再使用的内存空间。而闭包的“神奇”之处正是可以阻止这件事情的发生。拜 bar() 所声明的位置所赐,它拥有涵盖 foo() 内部作用域的闭包,bar() 本身在使用这个内部作用域,使得该作用域能够一 直存活,以供 bar() 在之后任何时间进行引用。 

本文章内容参考于《你不知道的JavaScript》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值