深入淺出 Scope Chain 與 Closure

栏目: JavaScript · 发布时间: 6年前

内容简介:Closure 是 ECMAScript 的一大特色,但由於對其不了解,因此很多人不敢使用 Closure;或者雖然會使用 Closure,但仍然對其原理一知半解。本文以 Runtime 角度深入探討 Closure 底層機制 Scope Chain,讓我們徹底了解 Closure 的黑魔法。ECMAScript 5

Closure 是 ECMAScript 的一大特色,但由於對其不了解,因此很多人不敢使用 Closure;或者雖然會使用 Closure,但仍然對其原理一知半解。

本文以 Runtime 角度深入探討 Closure 底層機制 Scope Chain,讓我們徹底了解 Closure 的黑魔法。

Version

ECMAScript 5

ECMAScript 2015

Definition

Closure

當 function 的執行 scope 已經離開 function 所定義的 scope 時,該 function 依然能夠抓到原 scope 的 variable 繼續執行

ECMAScript 5

const makeCounter = function(initial) {
  return function(step) {
    return initial += step;
  }
};

const counter = makeCounter(2);

console.log(counter(1)); // 3
console.log(counter(2)); // 5
console.log(counter(3)); // 8

ECMAScript 2015

const makeCounter = initial =>
  step => initial += step;

const counter = makeCounter(2);

console.log(counter(1)); // 3
console.log(counter(2)); // 5
console.log(counter(3)); // 8

這是最簡單的 Closure,ES5 與 ES6 的寫法有一點點差異。

initial 是定義在 makeCounter() scope 內,然後 return Anonymous function 給 counter

counter() 執行時,還能抓到 initial parameter,這就是 Closure

Stack 疑雲

我們知道 function 與 method 的 parameter 與 local variable,在執行時期都是存放在 Stack。

執行 makeCounter() 時, initial parameter 是存放在 Stack,當 makeCounter() 回傳 function 給 counter 後,Stack 會釋放,因此 initial parameter 也會被釋放,為什麼再次執行 counter() 時,還會抓到 initial parameter 呢 ?

Scope Chain

在 ECMAScript 中,所有的 variable 都是定義在 scope object 內,由 key / value 構成,也因為是 object, scope 是在 Heap 內。

const makeCounter = function(initial) {
  return function(step) {
    return initial += step;
  }
};

深入淺出 Scope Chain 與 Closure

在 code 執行前,ECMAScript 會將所有 variable 存在 global scope object 內。

因此我們有 key 為 makeCounter ,而 value 指向 function 的定義 object。

比較特別的是:每個 function object 有 hidden property [[scope]] 指向定義該 function 的 scope object。

makeCounter(2);

深入淺出 Scope Chain 與 Closure

當執行 makeCounter(2) 時,會有自己新的 function scope,因此會建立新的 scope object。

新的 scope object 一樣是由 key / value 構成,除了有 function 該有的 thisarguments 外,還有 initial parameter。

雖然我們是直接 return anonymous function,仍然可以想成有一個 key 為 f ,而 value 指向 function 的定義 object,他也有 [[scope]] 指向 makeCounter() 的 scope object。

比較特別的是:新的 function scope object 有一個 property : outer 指向定義 makeCounter() 的 global scope object,這個 reference 正是由 [[scope]] 複製而來。

const counter = makeCounter(2);

深入淺出 Scope Chain 與 Closure

在 global scope object 的 key 新增 counter ,其 value 指向所 return 的 anonymous function。

counter(1);

深入淺出 Scope Chain 與 Closure

當執行 counter(1) 時,又有新的 scope object 建立,一樣有 thisarguments ,也有 step parameter 為 1

outer property 亦由 [[scope]] 複製而來,因此可以指向 makeCounter() 的 scope object。

當要執行 initial += step 時,在 counter() 的 scope object 並沒有 key 為 initial 的 property,怎麼辦呢 ?

此時 ECMAScript 會透過 outer property 往上找,在 makeCounter() scope object 找到 initial

由於 scope object 會透過 outer[[scope]] 一層一層往上找,因此稱為 Scope Chain ,這是 Closure 之所以能正常執行的原因。

Conclusion

  • Scope object 因為是放在 Heap,而不是放在 Stack,因此不會隨著 function 執行完而釋放
  • 只要 scope object 被其他 scope object 的 outer property 所參考,則 ECMAScript runtime 的 Garbage Collection 就不會釋放該 scope object,因此 Closure 可以正常執行

以上所述就是小编给大家介绍的《深入淺出 Scope Chain 與 Closure》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言程序设计现代方法

C语言程序设计现代方法

K. N. King / 人民邮电出版社 / 2007-11 / 55.00元

《C语言程序设计现代方法》最主要的一个目的就是通过一种“现代方法”来介绍C语言,实现客观评价C语言、强调标准化C语言、强调软件工程、不再强调“手工优化”、强调与c++语言的兼容性的目标。《C语言程序设计现代方法》分为C语言的基础特性。C语言的高级特性、C语言标准库和参考资料4个部分。每章都有“问与答”小节,给出一系列与本章内容相关的问题及其答案,此外还包含适量的习题。一起来看看 《C语言程序设计现代方法》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具