JavaScript作用域和闭包

作用域
JavaScript的作用域限定了你可以访问哪些变量 。 有两种作用域:全局作用域 , 局部作用域 。
工具/原料JavaScript
方法/步骤1全局作用域
在所有函数声明或者大括号之外定义的变量 , 都在全局作用域里 。
不过这个规则只在浏览器中运行的JavaScript里有效 。

JavaScript作用域和闭包

文章插图

2可以在全局作用域定义变量 , 并不推荐这样做 。 因为可能会引起命名冲突 , 两个或更多的变量使用相同的变量名 。 在定义变量时使用了const或者let , 那么在命名有冲突时 , 就会收到错误提示 。 这是不可取的 。

JavaScript作用域和闭包

文章插图

3所以 , 应该尽量使用局部变量 , 而不是全局变量
局部作用域
在代码某一个具体范围内使用的变量都可以在局部作用域内定义 。 这就是局部变量 。
JavaScript里有两种局部作用域:函数作用域和块级作用域 。
从函数作用域开始 。
函数作用域
在函数里定义一个变量时 , 它在函数内任何地方都可以使用 。 在函数之外 , 就无法访问它了 。
比如下面这个例子 , 在sayHello函数内的hello变量:

JavaScript作用域和闭包

文章插图

4块级作用域是函数作用域的子集 , 因为函数是需要用大括号定义的 , (除非你明确使用return语句和箭头函数) 。
函数提升和作用域
当使用function定义时 , 这个函数都会被提升到当前作用域的顶部 。 因此 , 下面的代码是等效的:

JavaScript作用域和闭包

文章插图

5因为这里有两个变量 , 函数提升可能会导致混乱 , 因此就不会生效 。 所以一定要在使用函数之前定义函数 。
函数不能访问其他函数的作用域
在分别定义的不同的函数时 , 虽然可以在一个函数里调用一个函数 , 但一个函数依然不能访问其他函数的作用域内部 。
下面这例 , second就不能访问firstFunctionVariable这一变量 。

JavaScript作用域和闭包

文章插图

6嵌套作用域
如果在函数内部又定义了函数 , 那么内层函数可以访问外层函数的变量 , 但反过来则不行 。 这样的效果就是词法作用域 。
外层函数并不能访问内部函数的变量 。

JavaScript作用域和闭包

文章插图

7如果把作用域的机制可视化 , 可以想象有一个双向镜(单面透视玻璃) 。 能从里面看到外面 , 但是外面的人不能看到你 。

JavaScript作用域和闭包

文章插图

8函数作用域就像是双向镜一样 。 可以从里面向外看 , 但是外面看不到你 。
嵌套的作用域也是相似的机制 , 只是相当于有更多的双向镜 。

JavaScript作用域和闭包

文章插图

9【JavaScript作用域和闭包】多层函数就意味着多个双向镜 。
理解前面关于作用域的部分 , 就能理解闭包是什么了 。
闭包
在一个函数内新建另一个函数时 , 就相当于创建了一个闭包 。 内层函数就是闭包 。 通常情况下 , 为了能够使得外部函数的内部变量可以访问 , 一般都会返回这个闭包 。

推荐阅读