《你不知道的JavaScript(上卷)》 4.13 第五章作用域闭包

本文深入探讨了JavaScript中的闭包,揭示其本质并非神秘的语法特性,而是词法作用域的自然结果。通过实例解析,展示了闭包如何在函数执行外部保持对内部作用域的引用,防止垃圾回收。作者强调了闭包在异步操作如定时器、事件监听中的广泛应用,并通过解决循环中闭包的问题,展示了块作用域的重要性。文章最后指出,理解和掌握闭包对于提升JavaScript编程技巧至关重要。
摘要由CSDN通过智能技术生成

《你不知道的JavaScript (上卷)》

5.1启示

闭包并不是一个需要学习新的语法或模式才能使用的工具, 它也不是一件必须接受像 Luke2 一样的原力训练才能使用和掌握的武器。
闭包是基于词法作用域书写代码时所产生的自然结果, 你甚至不需要为了利用它们而有意
识地创建闭包。 闭包的创建和使用在你的代码中随处可见。 你缺少的是根据你自己的意愿
来识别、 拥抱和影响闭包的思维环境。

5.2实质问题

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

eg :

function foo() {
	var a = 2;
	function bar() {
		console.log( a ); // 2
	}
	bar();
}
foo();

这段代码看起来和嵌套作用域中的示例代码很相似。 基于词法作用域的查找规则, 函数
bar() 可以访问外部作用域中的变量 a

OK那么现在请问,这是闭包吗?

技术上来讲, 也许是。 但根据前面的定义, 确切地说并不是。 我认为最准确地用来解释
bar() 对 a 的引用的方法是词法作用域的查找规则, 而这些规则只是闭包的一部分。(但却
是非常重要的一部分! )

让我们清晰的展示闭包:

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

bar() 显然可以被正常执行。 但是在这个例子中, 它在自己定义的词法作用域以外的地方
执行。

在 foo() 执行后, 通常会期待 foo() 的整个内部作用域都被销毁, 因为我们知道引擎有垃
圾回收器用来释放不再使用的内存空间。 由于看上去 foo() 的内容不会再被使用, 所以很
自然地会考虑对其进行回收。
而闭包的“神奇” 之处正是可以阻止这件事情的发生。 事实上内部作用域依然存在, 因此
没有被回收。 谁在使用这个内部作用域? 原来是 bar() 本身在使用。

拜 bar() 所声明的位置所赐, 它拥有涵盖 foo() 内部作用域的闭包, 使得该作用域能够一
直存活, 以供 bar() 在之后任何时间进行引用。
bar() 依然持有对该作用域的引用, 而这个引用就叫作闭包

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

5.3清晰些许

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

5.4循环和闭包

块作用域和闭包联手便可天下无敌

我们对这段代码行为的预期是分别输出数字 1~5, 每秒一次, 每次一个

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

利用立即执行表达式改进:

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

再利用块作用域:

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

Be yourself, man, be proud of who you are.
Even if it sounds corny.
Never let no one tell you you ain’t beautiful.

Page 42 ~ Page 51 2021.04.13 21:09

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值