能夠讀懂這篇博客的JavaScript開發者,運氣不會太差…
1. 立即執行函數
立即執行函數,即Immediately Invoked Function Expression (IIFE),正如它的名字,就是創建函數的同時立即執行。它沒有綁定任何事件,也無需等待任何異步操作:
(function() { // 代碼 // ...})();function(){…}是一個匿名函數,包圍它的一對括號將其轉換為一個表達式,緊跟其后的一對括號調用了這個函數。立即執行函數也可以理解為立即調用一個匿名函數。立即執行函數最常見的應用場景就是:將var變量的作用域限制于你們函數內,這樣可以避免命名沖突。
2. 閉包
對于閉包(closure),當外部函數返回之后,內部函數依然可以訪問外部函數的變量。
function f1(){ var N = 0; // N是f1函數的局部變量 function f2() // f2是f1函數的內部函數,是閉包 { N += 1; // 內部函數f2中使用了外部函數f1中的變量N console.log(N); } return f2;}var result = f1();result(); // 輸出1result(); // 輸出2result(); // 輸出3代碼中,外部函數f1只執行了一次,變量N設為0,并將內部函數f2賦值給了變量result。由于外部函數f1已經執行完畢,其內部變量N應該在內存中被清除,然而事實并不是這樣:我們每次調用result的時候,發現變量N一直在內存中,并且在累加。為什么呢?這就是閉包的神奇之處了!
3. 使用閉包定義私有變量
通常,JavaScript開發者使用下劃線作為私有變量的前綴。但是實際上,這些變量依然可以被訪問和修改,并非真正的私有變量。這時,使用閉包可以定義真正的私有變量:
function Product() { var name; this.setName = function(value) { name = value; }; this.getName = function() { return name; };}var p = new Product();p.setName("Fundebug");console.log(p.name); // 輸出undefinedconsole.log(p.getName()); // 輸出Fundebug代碼中,對象p的的name屬性為私有屬性,使用p.name不能直接訪問。
4. prototype
每個JavaScript構造函數都有一個prototype屬性,用于設置所有實例對象需要共享的屬性和方法。prototype屬性不能列舉。JavaScript僅支持通過prototype屬性進行繼承屬性和方法。
function Rectangle(x, y){ this._length = x; this._breadth = y;}Rectangle.prototype.getDimensions = function(){ return { length: this._length, breadth: this._breadth };};var x = new Rectangle(3, 4);var y = new Rectangle(4, 3);console.log(x.getDimensions()); // { length: 3, breadth: 4 }console.log(y.getDimensions()); // { length: 4, breadth: 3 }代碼中,x和y都是構造函數Rectangle創建的對象實例,它們通過prototype繼承了getDimensions方法。
5. 模塊化
JavaScript并非模塊化編程語言,至少ES6落地之前都不是。然而對于一個復雜的Web應用,模塊化編程是一個最基本的要求。這時,可以使用立即執行函數來實現模塊化,正如很多JS庫比如jQuery以及我們Fundebug都是這樣實現的。
新聞熱點
疑難解答
圖片精選