Javascript 中一個最重要的特性就是閉包的使用。因為閉包的使用,當前作用域總可以訪問外部的作用域。因為 Javascript 沒有塊級作用域,只有函數作用域,所以閉包的使用與函數是緊密相關的。
模擬私有變量function Counter(start) { var count = start; return { increment: function() { count++; }, get: function() { return count; } } } var foo = Counter(4); foo.increment(); foo.get(); // 5
這里 Counter 返回兩個閉包:函數 increment 和 get。這兩個函數一直保持著對 Counter 作用域的訪問,因此它們能一直訪問到定義在 Counter 作用域的變量 count。
私有變量的工作機制由于 Javascript 不可以對作用域賦值和引用,所以在上例中,是沒有辦法在外部直接訪問內部私有變量 count。唯一的方法就是通過定義閉包來訪問。
var foo = new Counter(4); foo.hack = function() { count = 1337; };
上面的代碼不會改變 Counter 作用域內的 count 變量值,因為 hack 沒有在 Counter 內定義。上面這段代碼只會創建或者覆蓋全局變量 count。
循環內的閉包一個最容易犯的錯誤就是在循環內使用閉包。
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }
上面這段代碼不會輸出0到9,而是連續輸出10次10。
上面的匿名會一直保持一個對變量 i 的引用。當調用 console.log 函數開始輸出時,這是循環已經結束,而變量 i 已經為10了。
為了避免上面的錯誤發生,我們需要在每次循環時為變量 i 值創建一個拷貝。
為了復制循環中變量的值,最好的方式是在外層加一個匿名的立刻執行函數。
for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }
這個外部的匿名函數接收循環變量 i 作為第一個參數,并將其值拷貝至它自身的參數 e。
外部的匿名函數將參數 e 再傳遞給 setTimeout,因此 setTimeout 有了指向參數 e 的引用。而且這個參數 e 的值不會因為外部的循環改變而改變。
這里涉及到了立即執行函數,它的具體含義可以參考這個回答:
http://segmentfault.com/q/1010000000442042#a-1020000000442404
還有另外一個方法可以實現同樣的效果,就是在 setTimeout 內的匿名函數中再返回一個匿名函數:
for(var i = 0; i < 10; i++) { setTimeout((function(e) { return function() { console.log(e); } })(i), 1000) }
此外,通過 bind 方法也可以實現。
for(var i = 0; i < 10; i++) { setTimeout(console.log.bind(console, i), 1000); }參考
http://bonsaiden.github.io/JavaScript-Garden/#function.closures
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87517.html
Javascript 中的構造函數與其他語言相比也是不同的。任何通過關鍵字 new 調用的函數都可以當做構造函數。 在構造函數體內,this 指向新創建的對象。如果構造函數體內沒有顯示的 return 表達式,那么我們就默認返回 this,也就是新建的對象。 function Foo() { this.bla = 1; } Foo.prototype.test = function()...
摘要:并沒有類繼承模型,而是使用原型對象進行原型式繼承。我們舉例說明原型鏈查找機制當訪問一個對象的屬性時,會從對象本身開始往上遍歷整個原型鏈,直到找到對應屬性為止。原始類型有以下五種型。此外,試圖查找一個不存在屬性時將會遍歷整個原型鏈。 Javascript 并沒有類繼承模型,而是使用原型對象 prototype 進行原型式繼承。 盡管人們經常將此看做是 Javascript 的一個缺點,然...
摘要:閉包執行上下文決定了變量作用域而閉包,它其實是一種決策,是一種模式,讓我們可以靈活的改變變量作用域。所以,在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。只要咱們弄明白閉包,其中的自然跑不掉。 閉包 this 執行上下文決定了變量作用域 而閉包,它其實是一種決策,是一種模式,讓我們可以靈活的改變變量作用域。 按慣例,上栗子 var global = glo...
摘要:的操作符可以用來比較兩個操作數的構造函數。這是因為它們的構造函數不可能會是同一個對象。總結綜上所述,我們知道操作符最合適的使用壞境是比較兩個相同上下文背景下的自定義對象的構造函數,正如上篇介紹的操作符,其他壞境下使用作用不大。 Javascript 的 instanceof 操作符可以用來比較兩個操作數的構造函數 constructor。但這個只有在比較自定義對象才有意義。當用來比較 ...
摘要:在元素一篇介紹過,可以使用來使得代碼在加載完畢后自動執行代碼,接下來具體介紹下這個機制。這樣看上去貌似沒什么問題,但是如果有兩個函數需要指定時就會遇到麻煩,因為屬性只能保存對一個函數的引用,如果我們寫成以下形式最后代碼執行后的效果是會覆蓋。 在元素一篇介紹過,jQuery 可以使用 $(document).ready() 來使得代碼在 DOM 加載完畢后自動執行代碼,接下來具體介紹下這...
閱讀 480·2023-04-25 17:26
閱讀 1499·2021-08-05 09:58
閱讀 1966·2019-08-30 13:17
閱讀 950·2019-08-28 17:52
閱讀 1065·2019-08-26 18:27
閱讀 1419·2019-08-26 14:05
閱讀 3616·2019-08-26 14:05
閱讀 1593·2019-08-26 10:45