《深入理解JavaScript》——1.13 变量作用域和闭包

简介:

本节书摘来自异步社区《深入理解JavaScript》一书中的第1章,第1.13节,作者: 【美】AxelRauschmayer(罗彻麦尔)译者: 王玉林 , 杜欢 , 庄婷婷 , 章子鹏,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.13 变量作用域和闭包

在JavaScript中,通过在变量前使用var语句声明变量:

  screenshot

你可以使用单个var语句声明和初始化多个变量:

  screenshot

但是我推荐使用单独声明每一个变量(原因参考26.4.1“语法”)。因此,我会将之前的语句重写为:

  screenshot

由于前置的缘故(参考1.13.2“变量的提升特性”),通常它的最佳实践是在一个函数的开始部分声明变量。

1.13.1 变量是函数作用域的
一个变量的作用域总是完整的函数(相对于当前块)。例如:

  screenshot

我们可以看到变量tmp并不局限于(1)行;直到函数结束它都存在。

1.13.2 变量的提升特性
所有变量声明都会被提升:声明会被移动到函数的开始处,而赋值则仍然会在原来的位置进行。例如,以下函数中的变量会被认为是在标记为(1)的这行声明的:

  screenshot

然而在程序内部,上述函数的执行过程其实是这样的:

  screenshot

1.13.3 闭包
每个函数都和它周围的变量保持着连接,哪怕它离开被创建时的作用域也是如此。例如:

  screenshot

函数从标记为(1)的这行开始被创建,在创建结束后即离开它的上下文环境,但它仍然保持着和start的连接:

  screenshot

函数以及它所连接的周围作用域中的变量即为闭包。所以,create Incrementor()的返回其实就是一个闭包。

1.13.4 IIFE模式:引入一个新的作用域
有时你会想要引入一个新的作用域,例如,防止一个变量变成全局变量。在JavaScript中,不能通过块来做,必须使用函数。不过有一种模式可以将函数当做类似块的方式来使用。这种模式被称作为IIFE(立即调用函数表达式,发音为“iffy”):

  screenshot

请务必键入以上示例(注释除外)。IIFE是一个在定义之后就被立即调用的函数表达式。在函数内部,会有一个新的作用域,以防止tmp变成全局变量。更多关于IIFE的细节,参见16.6“通过IIFE引入新的作用域”。

IIFE用例:闭包造成的无意共享
闭包会持续地保持与外部变量的连接,而这有时候并不是你想要的:

 screenshot

标记为(1)的这行返回值总是i的当前值,而并非函数被创建时的值。在循环结束之后,i的值为5,所以数组中所有的函数都返回这个数值。如果你想要标记(1)这行的函数获得当前i值的一个快照,那么你可以使用IIFE:

  screenshot

相关文章
|
16天前
|
JavaScript 前端开发
js变量的作用域、作用域链、数据类型和转换应用案例
【4月更文挑战第27天】JavaScript 中变量有全局和局部作用域,全局变量在所有地方可访问,局部变量只限其定义的代码块。作用域链允许变量在当前块未定义时向上搜索父级作用域。语言支持多种数据类型,如字符串、数字、布尔值,可通过 `typeof` 检查类型。转换数据类型用 `parseInt` 或 `parseFloat`,将字符串转为数值。
18 1
|
20天前
|
自然语言处理 JavaScript 前端开发
JavaScript中闭包:概念、用途与潜在问题
【4月更文挑战第22天】JavaScript中的闭包是函数及其相关词法环境的组合,允许访问外部作用域,常用于数据封装、回调函数和装饰器。然而,不恰当使用可能导致内存泄漏和性能下降。为避免问题,需及时解除引用,减少不必要的闭包,以及优化闭包使用。理解并慎用闭包是关键。
|
1月前
|
JavaScript
|
1月前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
21 6
|
12天前
|
存储 JavaScript 前端开发
【JavaScript技术专栏】JavaScript基础入门:变量、数据类型与运算符
【4月更文挑战第30天】本文介绍了JavaScript的基础知识,包括变量(var、let、const)、数据类型(Number、String、Boolean、Undefined、Null及Object、Array)和运算符(算术、赋值、比较、逻辑)。通过实例展示了如何声明变量、操作数据类型以及使用运算符执行数学和逻辑运算。了解这些基础知识对初学者至关重要,是进阶学习JavaScript的关键。
|
6天前
|
前端开发 JavaScript
闭包在JavaScript中有许多应用场景
闭包在JavaScript中发挥关键作用,如封装私有变量和函数提升安全性,维护变量生命周期,实现高阶函数,模拟块级作用域,支持回调函数以处理异步操作,以及促进模块化编程,增强代码组织和管理。闭包是理解和掌握JavaScript高级特性的重要一环。
21 7
|
6天前
|
存储 JavaScript 前端开发
js的变量以及运算
js的变量以及运算
12 1
|
6天前
|
JavaScript 前端开发
关于js变量
关于js变量
16 1
|
6天前
|
JavaScript 前端开发
js的变量
js的变量
13 2
|
12天前
|
自然语言处理 JavaScript 前端开发
【JavaScript技术专栏】深入理解JavaScript作用域与闭包
【4月更文挑战第30天】了解JavaScript的关键在于掌握作用域和闭包。作用域决定变量和函数的可访问范围,分为全局(在`window`或`global`对象中)和局部(函数内部)。闭包则允许函数访问其创建时的作用域,即使在其他地方调用。它通过作用域链保存对外部变量的引用,常用于实现私有变量、模块化和柯里化。然而,不当使用闭包可能导致内存泄漏和性能下降。理解这些概念能提升代码质量,但也需谨慎处理潜在问题。