這篇文章帶給大家的內容是關於js中閉包與立即執行函數的使用介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
前言:最近在細讀Javascript高級程式設計,對於我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程式設計第三版》。
作用域鏈的這種配置機制引出了一個值得注意的副作用,即閉包只能取得包含任何變數的最後一個值。
function createArray(){ var result = new Array(); for(var i = 0; i < 10; i++) { result[i] = function() { return i; } } return result; }
這個函數會回傳一個函數陣列。表面上看,似乎每個函數都應該傳回自己的索引值,即位置0的函數傳回0,位置1的函數回傳1,以此類推。
但實際上,每個函數都返回10,因為每個函數的作用域中都保存著createArray的活動對象,所以他們引用的都是同一個變數i。
當createArray()函數回傳後,變數i的值是10,此時每個函數都引用同一個變數i,所以i的值是10。
// 代码执行过程 createArray(); /* createArray() { var result = new Array(); var i; // 0,1,2,3,4,5,6,7,8,9,10 for ( i = 0; i < 10 ; i ++) { result[i] = function() { return i; // 注意 函数的执行时机,你只有调用函数的时候,才会产生执行环境,沿着作用域链,找到活动对象 // 这里有个闭包,还记得闭包的概念吗? 有权访问到另外一个函数作用域的变量的函数 } } /* result[0] = function(){ return i } result[1] = function(){ return i } result[2] = function(){ return i } .... */ return result; } result = [function(){return i}, function(){return i}....]; */ createArray()[1](); // 10
那麼如何讓這個函數的行為符合我們的預期呢?
可以透過建立另一個匿名函數來強制讓閉包的行為符合預期,這裡也應用了立即執行函數。
//立即执行函数 //我们平时写函数然后调用是这么写的。 //声明函数,调用执行。 function foo(){ console.log("hi"); } foo(); // "hi" //那么,我们可不可以声明调用写一块呢? 这就是申明函数立刻执行。 //好像不可以,控制台报错 function foo(){ console.log("hi"); }(); //Uncaught SyntaxError: Unexpected token ) //那么如果用括号包裹呢? (function foo(){ console.log("hi"); }()); // "hi", 可以了。 这就是立即执行函数!
有了立即執行函數,就可以強制讓閉包的行為符合我們的預期了。
//改写代码 function createArray() { var result = new Array(); for( var i = 0; i < 10; i ++ ) { result[i] = (function(i) { return function(){ return i; } }(i)); } return result; } createArray()[0](); // 0 createArray()[1](); // 1 createArray()[2](); // 2 // 这里不只有一种方法,其他方法在此不表。
以上是js中閉包與立即執行函數的使用介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!