本文實例講述了JavaScript閉包與作用域鏈。分享給大家供大家參考,具體如下:
閉包定義
閉包指的是有權訪問另一個函數作用域中的變量的函數。創建閉包的常見方式,就是在一個函數A內部創建另一個函數B,那么函數B就是一個閉包,可以訪問函數A作用域中的所有變量。
JavaScript的閉包與作用域鏈密不可分,因此本文可以和JavaScript的作用域鏈相對照分析,一定可以對JavaScript的閉包和作用域鏈有更深的理解。
下面我們仍然以createComparisonFunction為例進行閉包的分析。
//step1: define createComparisonFunctionfunction createComparisonFunction(propertyName){ return function(object1, object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } };}//step2: call createComparisonFunctionvar compareName = createComparisonFunction("name");var compareAge = createComparisonFunction("age");//step3: call comparevar object1 = { name : "Nicholas", age : 25};var object2 = { name : "Greg", age : 27};var result1 = compareName(object1, object2); // 1var result2 = compareAge(object1, object2); // -1//step4: dereference closure for recycle memorycompareName = null;compareAge = null;在這個例子中,匿名函數function(object1, object2)是一個閉包,能訪問createComparisonFunction作用域里的所有變量,自然也包含propertyName屬性, 因為propertyName參數的不同,導致比較的屬性也有所不同,從而函數執行結果也有不同。
閉包與變量
從JavaScript的作用域鏈中,我們了解到JavaScript是通過作用域鏈來確定函數執行環境的作用域的,這種機制會引出一個值得注意的副作用,即閉包只能取得包含函數中任何變量的最后一個值。閉包是通過引用外部函數的活動對象來訪問該活動對象中的所有變量,因此在外部函數執行過程中,這些變量的值可能會變化,但是在外部函數執行完畢之后,外部函數的活動對象便不會再改變,因此在執行閉包的時候,閉包通過作用域鏈訪問到外部函數的活動對象中的所有變量都只可能是在外部函數執行完畢之后,外部函數的活動對象中最后所保存的值。我們通過一個例子來說明這種副作用。
function createFunctions(){ var result = new Array(); for (var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result;}var functions = createFunctions();for(var i = 0; i < functions.length; i++){ console.log(functions[i]());}輸出的結果是
10 10 10 10 10 10 10 10 10 10
從表面上看,似乎每個函數都應該返回自己的索引值,但實際上,每個函數都返回10。因為每個函數的作用域鏈中都保存著createFunctions函數的活動對象,所以他們引用的都是這個createFunctions函數的活動對象中的變量i,在createFunctions函數返回之后,變量i的值是10,此時每個函數都引用著保存變量i的同一個變量對象,所以每個函數內部i的值都是10。
新聞熱點
疑難解答
圖片精選