前言
这个系列是翻译自 nodeschool.io中的 scope-chains-closures
直接闯关:
npm install -g scope-chains-closures
scope-chains-closures
作用域链和闭包
作用域,作用域链,闭包和垃圾回收机制都有一个共同点:学了就忘!
闭包到底是干啥的?
啥时候发生垃圾回收机制?
作用域链到底是啥?
这个教程让你发现这些都是小意思。让你在实践中学习!
任务一 作用域
作用域的主要类型是词法作用域
。
简单来说是function
创建的作用域。(ES6中的块级作用域暂且不提)
初始化变量
变量的初始化取决于作用域的类型
词法作用域
var
用来将变量定义在词法作用域中(也就是function中)
function someFunc(){
var a;
}
a
就被函数someFunc
框在了词法作用域中
块级作用域
let
和const
用来将变量定义在块级作用域中(也就是花括号中)
if(true){
let b;
}
b
就被if
的花括号框在了块级作用域中
你的任务
在空白的js文件中新建一个函数foo
,并包含一个词法作用域中的变量bar
任务二 作用域链
作用域嵌套
作用域是可以嵌套的,任务一中提到的词法作用域和块级作用域都可以嵌套其他作用域
(块级作用域仅对ES6而言)
function someFunc(){
function inner(){
}
}
inner
就是嵌套在someFunc
(词法作用域)中的词法作用域
if(true){
while(false){
}
}
while
就是嵌套在if
(块级作用域)中的块级作用域
function someFunc(){
if(true){
}
}
if
就是嵌套在someFunc
(词法作用域)中的块级作用域
作用域中的变量访问
所有的嵌套作用域都遵循以下规则:
内部作用域有权访问外部作用域,反之不成立。
栗子:
function someFunc(){
var outerVar = 1;
function inner(){
var innerVar = 2;
}
}
inner
有权访问innerVar
和outerVar
,但是someFunc
只能访问到outerVar
多重嵌套作用域
作用域是可以任意嵌套的,但是都要遵循上面的规则。
再附加一个规则:
兄弟作用域不可相互访问
栗子:
function someFunc(){
function inner(){
}
function inner2(){
}
}
inner
和inner2
都是someFunc
中的作用域,正如someFunc
不能访问inner
们的作用域一样,inner
们之间也不能相互访问。
作用域树
从上向下看这个嵌套作用域,就是棵树!
看代码:
function someFunc() {
function inner() {
}
function inner2() {
function foo() {
}
}
}
看树:
someFunc()
|
/ \
/ \
/ \
↓ ↓
inner() inner2()
|
↓
foo()
要记住的是:inner作用域可以访问外部作用域,但是反之不成立(foo()
可以访问inner2()
中的变量,inner2()
可以访问someFunc()
中的变量),这棵树倒过来似乎更有意义,就成了链!!
作用域链
从最里面看到最外面就构成了作用域链
someFunc()
↑
\
\
\
inner2()
↑
|
foo()
你的任务
修改任务一中的代码,让foo
中包含一个函数zip
,同时zip
也包含一个变量quux
完成后执行:scope-chains-closures verify
验证答案
附录
scope-chains-closures workshop
scope cheatsheet