在編程語言中,做用域控制着變量與參數的可見性及生命週期,它能減小名稱衝突,並且提供了自動內存管理 --javascript 語言精粹javascript
我理解的是,一個變量、函數或者成員能夠在代碼中訪問到的範圍。java
js的變量做用域是基於其特有的做用域鏈的。編程
全局變量都是window對象的屬性閉包
沒有塊級做用域編程語言
函數中聲明的變量在整個函數中都有定義。函數
//全局做用域 var a = 10; //沒有塊級做用域 if(fasle){ var b =2; } //函數做用域 function f(){ var a = 1; console.log(a); }
做用域鏈是一個對象列表,上下文代碼中出現的標識符在這個列表中進行查找。code
若是一個變量在函數自身的做用域(在自身的變量/活動對象)中沒有找到,那麼將會查找它父函數(外層函數)的變量對象,以此類推。對象
舉個栗子:生命週期
function f (){ var x =100; function g(){ console.log(x); } g(); } f();
這裏造成了一條做用域鏈,當函數g訪問不到變量時,它會經過內部的[[scope]]對象查找做用域鏈上的執行上下文,當找到就終止,找不到會繼續,直到window對象上也沒有的時候,會報錯。ip
須要注意的是,用new Function
建立的函數,其做用域指向全局做用域。
function f(){ var x = 100; // g.[[scope]] == window var g = new Function("", "alert(x)"); g(); } f(); //報錯 x is not defined
在計算機科學中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數閉包(function closures),是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外。因此,有另外一種說法認爲閉包是由函數和與其相關的引用環境組合而成的實體。--維基百科
個人理解就是,一個函數捕獲其父函數的自由變量,這就造成了閉包。
栗子:
function f1(){ var a = 10; var b = 20; return function f2(){ console.log(a); } } var result = f1(); result();
做用域鏈的存在
減小全局變量
減小傳遞給函數的參數數量
封裝
對捕獲的變量只是個引用,不是複製
function f(){ var num = 1; function g(){ alert(num); } num++; g(); //2 } f();
父函數每調用一次,會產生不一樣的閉包
function f(){ var num = 1; return function(){ num++; alert(num); } } var result1 =f(); result1(); result1(); var result2 =f(); result2(); result2(); //兩次都彈出同樣的數值
循環中出現的問題
for (var i = 1; i <= 3; i++) { var ele = document.getElementById(i); ele.onclick = function(){ alert(i); } }; // i爲4
解決方法:
for (var i = 1; i <= 3; i++) { var ele = document.getElementById(i); ele.onclick = (function(id){ return function(){ alert(id); }})(i); }; // 1,2,3