Javascript 作用域鏈、閉包的理解和應用

1. 什么是作用域,作用域鏈

作用域,指代碼所在的執(zhí)行環(huán)境。
代碼執(zhí)行時產(chǎn)生的最先產(chǎn)生的執(zhí)行環(huán)境,稱為全局作用域, 如瀏覽器為 window, node 為 global. 作用域內(nèi)部執(zhí)行時產(chǎn)生的、新的作用域為局部作用域。(es5 不存在塊級作用域,作用域僅通過函數(shù)作用域分隔。而 es6 中通過 let 和 const 聲明的變量和常量,在 if 和 for 的執(zhí)行部分擁有塊級作用域。)

    // 塊級作用域
    for(let i = 0; i < 3; i++) {
        console.log(i) // 依次打印 1, 2, 3
    }
    console.log(i) // 報錯: Uncaught ReferenceError: i is not defined

由此逐層衍生、逐層嵌套的作用域,稱之為作用域鏈。它們擁有以下的特性:

1-1 外層作用域無法調(diào)用內(nèi)層作用域的變量和常量。比如,全局作用域無法調(diào)用局部作用域聲明的變量或常量。

function func(){
    var foo = 111;
    console.log(foo)
}
func() // 111
console.log(foo) // 報錯: Uncaught ReferenceError: foo is not defined

1-2 代碼執(zhí)行需要時,優(yōu)先引用當前所在執(zhí)行環(huán)境中的變量和常量;當前執(zhí)行環(huán)境不存在引用到的對象時,則追測其所在作用域鏈的上游。因此:任何局部作用域都可引用全局變量。

var foo = 111;
function func(){
    console.log(foo)
}
func() // 111

1-3 直至追溯到最外層作用域(如上所說的 window 或 global)仍未定義的引用,即為 not defined.

2. 作用域的特殊情況

es5 非嚴格模式下,當在局部作用域不聲明、賦值一個變量時, 產(chǎn)生的是一個全局變量。

// 非嚴格模式下
function test() {
    a = 111;
}
test();
console.log(a); // 111

3. 什么是閉包,如何產(chǎn)生?有哪些應用?優(yōu)缺點分別是什么?

當函數(shù)執(zhí)行完成后,返回一個值時,當前執(zhí)行環(huán)境會被清理掉。但是當函數(shù)返回一個調(diào)用了局部變量的函數(shù)時,外層函數(shù)的執(zhí)行環(huán)境不會被清理掉,此作用域內(nèi)的變量仍能被返回的函數(shù)引用。由此形成的即為閉包。

閉包應用

3-1 例1:對應位置的斐波那契數(shù)

const fib = (() => {
  // 利用閉包避免重復計算
  let cache = { 1: 1, 2: 1 };
  const func = num => {
    // 避免誤傳非正整數(shù)造成死循環(huán)
    let n = parseInt(num) >= 1 ? parseInt(num) : 1;
    if (cache[n]) return cache[n];
    // 遞歸
    return (cache[n] = func(n - 2) + func(n - 1));
  };
  return func;
})();

console.log( fib(5) ) // 8

3-2 例2:通過調(diào)用返回的函數(shù), 形成一個外部作用域能夠獲取、修改局部變量的間接渠道。

 function closure() {
     let n = 0;
     return {
         add: (m = 1 ) => n+=m,
         minus: (m = 1) => n-=m,
         getN: () => n
     }
 }
 
 // 外層作用域無法直接獲取和修改 n; 但是可以通過 closure 返回的函數(shù),進行獲取和操作。
 const {add, minus, getN} = closure()
getN(); // 0
add(2);
getN(); // 2
minus();
getN(); // 1
優(yōu)缺點

優(yōu)點:對于可能重復的運算,進行緩存;

缺點:當運算數(shù)字過大時,會產(chǎn)生內(nèi)存占用;影響整體性能;

關(guān)聯(lián)文章:

再談對 Javascript 作用域的理解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容