4

前言

这个系列是翻译自 nodeschool.io中的 scope-chains-closures

直接闯关:

npm install -g scope-chains-closures

scope-chains-closures

作用域链和闭包

作用域,作用域链,闭包和垃圾回收机制都有一个共同点:学了就忘!
闭包到底是干啥的?
啥时候发生垃圾回收机制?
作用域链到底是啥?

这个教程让你发现这些都是小意思。让你在实践中学习!

任务一 作用域

作用域的主要类型是词法作用域
简单来说是function创建的作用域。(ES6中的块级作用域暂且不提)

初始化变量

变量的初始化取决于作用域的类型

词法作用域

var用来将变量定义在词法作用域中(也就是function中)

function someFunc(){
    var a;
}

a就被函数someFunc框在了词法作用域中

块级作用域

letconst用来将变量定义在块级作用域中(也就是花括号中)

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有权访问innerVarouterVar,但是someFunc只能访问到outerVar

多重嵌套作用域

作用域是可以任意嵌套的,但是都要遵循上面的规则。
再附加一个规则:
兄弟作用域不可相互访问

栗子:

function someFunc(){
    function inner(){
    }
    function inner2(){
    }
}

innerinner2都是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 <your-file.js> 验证答案

附录

scope-chains-closures workshop
scope cheatsheet


savokiss
6.2k 声望4.5k 粉丝

You know nothing, SpongeBob.