JavaScript 做用域、命名空間及閉包

變量做用域:閉包

  一、一個變量的做用域是程序源代碼中定義這個變量的區域函數

  二、在函數內聲明的變量是局部變量,它只在該函數及其嵌套做用域裏可見(js 函數可嵌套定義);不在任何函數內聲明或在函數內不使用 var 或 let 關鍵字聲明的變量是全局變量,它在整個 JavaScript 程序裏均可見spa

  三、JavaScript 中沒有塊級做用域,取而代之的是函數做用域code

  四、局部變量會遮蓋全局變量對象

  五、注意變量的聲明提早,即全部變量都會把聲明提早到它的做用域頂端blog

  六、若使用 let 聲明變量,則該變量只屬於就近的花括號括起來的語句塊!!!ip

let test = "global"; function fun() { let test = "local"; // 若改爲 test = "local"; 則會修改全局變量 test
    console.log("inFun: ", test); } fun(); // 輸出 local
console.log("outFun: ", test);  // 輸出 global


var j = 10; // 因爲聲明提早,因此函數內的 j != 10
function check() { var i = 0; // 由於函數做用域,因此會出現聲明提早的現象(let 聲明除外),即變量聲明以前就能夠使用,但其值爲 undefined
    console.log("j = ", j); for (var j = 0; j < 5; ++j) i++; console.log("i = ", i, "j = ", j); } check(); // 輸出 j = undefined i = 5 j = 5

 

命名空間:作用域

   通常狀況下,在 JavaScript 中是沒法聲明只在一個代碼塊內可見的變量(let 能夠聲明),基於這個緣由,咱們經常會簡單地定義一個函數用做臨時的命名空間io

// function 前面的左圓括號是必須的,若省略則會將關鍵字 function 解析爲函數聲明語句, // 而不是正確地解析爲函數定義表達式
var sum = (function () { var a = 2, b = 3;   // 在這裏面定義的變量沒法從外面訪問,因此不會污染全局命名空間
    return a + b; }()); // 後面的圓括號表示結束函數定義並當即調用它
console.log(sum);   // 輸出 5

 

做用域鏈:console

  若是將一個局部變量看做是自定義實現的對象的屬性的話,每一段 JavaScript 代碼(全局代碼或函數)都有一個與之相關的做用域鏈。這個做用域鏈是一個對象列表或鏈表,定義了這段代碼「做用域中」 的變量。當 JavaScript 須要查找某個變量時,它會從鏈中的第一個對象開始查找,若未找到,則查找下一個對象,以此類推。若是做用域鏈上沒有任何一個對象符合查找內容,則會拋出一個引用錯誤異常。

let global = "globalOne"; function f() { let global = "globalTwo"; function f1() { let global = "globalThree"; } } /* 在這段代碼裏 global 的值在做用域鏈裏爲:globalThree -> globalTwo -> globalOne, 若查詢代碼在 f1 裏,則會從 globalThree 開始尋找,若在 f 裏,則從 globalTwo 開始尋找 若找不到,則往箭頭方向繼續尋找下去,箭頭反方向對它是不可見的 */

 

閉包:

   函數對象能夠經過做用域鏈相互關聯起來,函數體內部的變量均可以保存在函數做用域內,這種特性在計算機科學文獻中被稱爲「閉包」。從技術角度講,全部的 JavaScript 函數都是閉包

var counter = (function () { var count = 0; return function () { return ++count; }; }()); // 自我調用函數只執行一次。設置計數器爲 0。並返回函數表達式。
console.log(counter()); // 輸出 1
console.log(counter()); // 輸出 2
console.log(counter()); // 輸出 3

 注:命名空間一般也是一個函數

// 同一個做用域鏈內定義的閉包會共享一樣的私有變量或變量 // 如下代碼生成 10 個閉包,全部閉包共享變量 i
function constfuncs() { var funcs = []; for (var i = 0; i < 10; ++i) funcs[i] = function () { return i;   // 嵌套函數不會將做用域內的私有成員複製一份,也不會對所綁定的變量生成靜態快照
 }; return funcs; } var funcs = constfuncs();   // 當 constfuncs 返回時 i = 10
console.log(funcs[5]());    // 輸出 10
相關文章
相關標籤/搜索