常用的JavaScript模式有哪些?模式是解決或者避免一些問題的方案。下面YJBYS小編為大家列出幾種常用的JavaScript模式,歡迎大家閱讀學習!
在JavaScript中,會用到一些常用的編碼模式。下面就列出了一些常用的JavaScript編碼模式,有的模式是為了解決特定的問題,有的則是幫助我們避免一些JavaScript中容易出現的錯誤。
單一var模式
所謂“單一var模式”(Single var pattern)就是指在函式頂部,只使用一個var進行變數宣告的模式。例如:
function func() {
var a = 1,
b = 2,
sum = a + b,
myObject = {}, i,
j;
// other code}
使用這個模式的好處:
在函式頂部展示了所有函式中使用的區域性變數
防止變數提升引起的問題
變數提升
JavaScript允許在函式的任意地方宣告變數,但是效果都等同於在函式頂部進行宣告,這個是所謂的變數提升(Hoisting)。
看一個例子:
var num = 10;
function func() {
alert(num); // undefined
var num = 1;
alert(num); // 1}func();
從這個例子可以看到,第一次alert的值並不是10,而是undefined。所以,應該儘量使用“單一var模式”來避免類似的問題。
關於變數提升的細節,請參考我前面一篇JavaScript的執行上下文。
for-in迴圈
在JavaScript中,for-in迴圈主要用來列舉物件的屬性。
但是,由於JavaScript中原型鏈的存在,一般都會結合hasOwnProperty()來使用for-in迴圈,從而過濾原型鏈上的非該物件的屬性。
var wilber = {
name: "Wilber",
age: 28,
gender: "male"};tPersonalInfo = function() { (, "is", , "years old");
};for(var prop in wilber) { if(wnProperty(prop)) { (prop, ":", wilber[prop]);
}
}
開放的大括號位置
根據開發人員的習慣,開放大括號的位置會有不同的選擇,可以和語句放在同一行,也可以放在新的一行:
var total = 10;if(tatal > 5) { ("bigger than 5");
}if(tatal > 5)
{ ("bigger than 5");
}
兩種形式的`程式碼都能實現同樣的邏輯,但是,JavaScript允許開發人員省略分號,JavaScript的分號插入機制(semicolon insertion mechanism)會負責加上省略的分號,這時開放大括號的位置不同就可能產生不同的結果。
看一個例子:
function func() { return
{
name: "Wilber"
};
}
alert(func());// undefined
之所以得到的結果是undefined就是因為JavaScript的分號插入機制,在return語句之後自動添加了分號。
調整一下開放的大括號的位置就可以避免這個問題:
function func() { return {
name: "Wilber"
};
}
alert(func());// [object]
所以,關於開放的大括號位置,建議將開放的大括號放置在前面語句的同一行。
強制new模式
JavaScript中,通過new關鍵字,可以用建構函式來建立物件,例如:
function Person(name, city) { = name; = city;
nfo = function() { (, "lives at", );
}
}var will = new Person("Will", "Shanghai");
nfo();// Will lives at Shanghai
但是,如果開發人員忘記了new關鍵字,那麼建構函式中的this將代表全域性物件(瀏覽器中就是window物件),所有的屬性將會變成全域性物件的屬性。
function Person(name, city) { = name; = city;
nfo = function() { (, "lives at", );
}
}var will = Person("Will", "Shanghai");();// Uncaught TypeError: Cannot read property 'name' of ();// ();// nfo();// Will lives at Shanghai
所以,為了避免這類問題的方式,首先是從程式碼規範上下手。建議對於所有的JavaScript建構函式的命名方式都遵循,建構函式使用首字母大寫的命名方式。
這樣當我們看到首字母大寫的函式,就要考慮是不是漏掉了new關鍵字。
自呼叫建構函式
當然除了規範之外,還可以通過程式碼的方式來避免上面的問題。
具體的做法就是,在建構函式中檢查this是否為建構函式的一個例項,如果不是,建構函式可以通過new關鍵字進行自呼叫。
下面就是使用自呼叫建構函式對上面的例子進行改進:
function Person(name, city) { if(!(this instanceof Person)) { return new Person(name, city);
}
= name; = city;
nfo = function() { (, "lives at", );
}
}var will = Person("Will", "Shanghai");();// ();// nfo();// Will lives at nfo();// Uncaught TypeError: nfo is not a function
結合建構函式的命名約定和自呼叫的建構函式,這下就不用擔心漏掉new關鍵字的情況了。
陣列性質檢查
當在JavaScript中判斷一個物件是不是陣列的時候,不能直接使用typeof,因為我們會得到object。
在ECMA5中提出了ray()這個函式,我們可以直接使用來判斷一個物件是不是陣列型別。
對於不支援ECMA5的環境,我們可以通過下面的方式自己實現ray()這個函式。
if(typeof ray === "undefined") { ray = function(arg){ return (arg) === "[object Array]";
};
}var arr = [];(ray(arr));// true
立即執行函式
立即執行函式是JavaScript中非常常用的一種模式,形式如下:
(function() {
// other code
}());
通過這個模式可以提供一個區域性的作用域,所以函式程式碼都會在區域性作用域中執行,不會汙染其他作用域。
現在的很多JavaScript庫都直接使用了這種模式,例如JQuery、underscore等等。
立即執行函式的引數
關於立即執行函式另外一點需要注意的地方就是立即執行函式的引數。
我們可以像正常的函式呼叫一樣進行引數傳遞:
(function(name, city) {
(name, "lives at", city);}("Wilber", "Shanghai"));// Wilber lives at Shanghai
在立即執行函式中,是可以訪問外部作用域的(當然包括全域性物件),例如:
var name = "Wilber";var city = "Shanghai";
(function() { (name, "lives at", city);
}());// Wilber lives at Shanghai
但是,如果立即執行函式需要訪問全域性物件,常用的模式就是將全域性物件以引數的方式傳遞給立即執行函式。
var name = "Wilber";var city = "Shanghai";
(function(global) { (, "lives at", );
}(this));// Wilber lives at Shanghai
這樣做的好處就是,在立即執行函式中訪問全域性變數的屬性的時候就不用進行作用域鏈查找了,關於更多JavaScript作用域鏈的內容,可以參考理解JavaScript的作用域鏈。
初始化時分支
初始化時分支(Init-time Branching)是一種常用的優化模式,就是說當某個條件在整個程式宣告週期內都不會發生改變的時候,不用每次都對條件進行判斷,僅僅一次判斷就足夠了。
這裡最常見的例子就是對瀏覽器的檢測,在下面的例子中,每次使用istener1屬性的時候都要進行瀏覽器判斷,效率比較低下:
var utils = {
addListener: function(el, type, fn) {
if (typeof ventListener === 'function') {
ventListener(type, fn, false);
} else if (typeof chEvent === 'function') { // IE chEvent('on' + type, fn);
} else { // older browsers el['on' + type] = fn;