2. 解释 Closure ( Scope chain )

定义


MDN的定义:

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).
In other words, a closure gives you access to an outer function’s scope from an inner function.
( 引用自 Closures - JavaScript | MDN )

『闭包(Closure)包含 函式以及该函式 被宣告时所在的作用域环境(lexical environment)。』
→ 环境包含闭包建立时,所有位於该作用域的区域变数。

而在JS的function creation phase里,每次function建立时都会产生closure(Scope Chain)。

可以参考前几篇文章的这张图回忆一下:
https://ithelp.ithome.com.tw/upload/images/20210903/20129476Q9VkPYnUJM.png

然後直接看例子:

let person = "Mary";

function f1(){
    let person = "Tina";
    console.log( person + " is tall."); // person = Tina
    f2();
}

function f2(){
    console.log( person + " is cute."); // person = Mary
}

f1(); // output: Tina is tall. ; Mary is cute.

最後一行要呼叫f1()时:

  1. f1()里本身就定义了一个person(Tina)。
  2. console.log person时,调用了被定义在f1()里的person(Tina)。
  3. 呼叫f2()

重点是,f2() 要去哪里找person?

这时候就会发挥closure的作用,也就是说:

  1. 要console.log person时,发现没有person → 往外层找
  2. 找到 global variable 的 person(Mary),把它印出来。

只记结论的话,就是当一个function要调用一个variable,而这个variable没被定义在function里,
function会从被定义的区块/阶层开始找变数。

Scope Chain


因此Closure也可以称作Scope Chain,( 我自己理解成Closure就像是被串在一起的Scope们。)

每个Closure都包含三个Scope:

  • Local Scope (Own scope) → 当前的scope
  • Outer Functions Scope → 和Local Scope有阶层关系的外层scope
  • Global Scope

改一下上面的例子:

// Global Scope
let person = "Mary";

function f1(){    // Outer Functions Scope
    let person = "Tina";
    console.log( person + " is tall."); 
    
    function f2(){
    console.log( person + " is cute.");    // Local Scope
    }
    
    f2(); 
}

f1(); // output: Tina is tall. ; Tina is cute.

所以这段script的阶层关系是,以f2()而言:

  1. f2() 本身是 Local Scope
  2. f1()f2() 来说是 Outer Functions Scope
  3. f1()之外都是 Global Scope

而最後印出的person,都是f1()里的"Tina",这就是基於closure的特性。

由此可见,一个scope chain的顺序关系会是
Local Scope (Own scope) → Outer Functions Scope → Global Scope

Closure vs. Scope


因为我自己在学的时候稍微会弄混,那为了更精辟的使用/了解这些特性,我试着用同个例子分别解释各两个名词。

举例:

let person = "Tina";

function f(){
    let person = "Winnie";
    console.log( person );
}

f(); // output: Winnie

因为scope是基於被宣告的位置,所以如果要解释scope,可以说:

  1. let person = "Tina"; 有 global scope
  2. f() 会建立一个function scope
  3. let person = "Winnie"; 则是有 function scope

而如果要解释closure,可以说:
f()会印出Winnie,是因为f()会从local scope里开始找person,这是基於function创建了closure。
而f()在local scope找到了叫做"Winnie"的person,所以呼叫f()的结果会是Winnie。

参考资料:

【如果内文有误,还希望请不吝指教>< 谢谢阅览至此的各位:D】

-----正文结束-----

虽然请大家不吝指教,结果我发现我还不能回文,我失职QQ


<<:  新新新手阅读 Angular 文件 - Day03

>>:  修复Windows 10/7/8「无法读取来源档案或磁碟」错误

【图解演算法教学】【Tree】二元树遍历 vs QuickSort

Youtube连结:https://bit.ly/30F3Swz 在我们了解Binary Tree...

Day-8 Hazard

Hazard tags: IT铁人 Pipeline隐忧 上一次我们提到Pipeline可以提升速度...

Day 24 : Linux - 常用且一定要会的指令有哪些?

如标题,这篇想和大家介绍一下有哪些你一定要会的Linux指令 首先,先用Ctrl + Alt + T...

Day2:进入新手村前先让我复习一下QQ-CSS-clear 清除浮动

clear 清除浮动 浮动元素顾名思义就是浮动在版面之上,所以如果接着顺序往下写的程序码没有使用cl...

Day-13 Excel交叉分析真的很难吗?

今日练习档ԅ( ¯་། ¯ԅ) 今天要与大家分享我所认为较进阶的枢纽分析表应用,也就是「交叉分析数据...