簡單而強大的JavaScript技巧

九哥發表於2015-04-28

本篇文章將會介紹和解析一些簡單但是強大的JavaScript技巧. 這些技巧所有的JavaScript程式設計師都可以馬上使用, 你不需要成為JavaScript高手才能理解這些.如果你還是新手, 而且讀完所有這些技巧的詳解和每種技巧是如果工作的以後運用它們, 你會寫出更加簡練高效的JavaScript程式.

強大的&&||表示式

你可能在JavaScript庫和JavaScript框架中已經見過它們了, 那麼我們先由幾個基本的例子開始:

Example 1:|| (或)

設定預設值,通常用:

function setKey(value){  
    if(!value){
       value = "Default Value"; 
    }
}

用這個代替:

function setKey(value){
    value = value || "Default Value";
}

!提示: JavaScript判斷為假的值: null,false,0, undefined, NaN""(空字串). 記住像Infinity(無限大)這種 Number(感謝@xyzhanjiang 的指正) 的值是被判斷為真不是假. 而NaN則被判斷為假. 除了以上這些, 其他值全部被判斷為真.

解析
- || 操作符首先從左開始判斷表示式的真假, 如果為真, 馬上返回左邊表示式返回的值; 如果左邊表示式被判斷為假, 則繼續判斷右邊的表示式, 並返回右邊表示式的值.
- 如果value被判斷為假, 會返回右邊表示式的值. 換句話說, 如果value變數被判斷為真, 則返回value的值.

Example 2:&&(並)

不要這麼做:

function isAdult(age){
    if(age && age > 17){
        return true;
    }else{
        return false;
    }
}

用這個代替:

function isAdult(age){
    return age && age > 17;
}

解析
- && 操作符從左開始判斷表示式, 如果左邊的表示式被判斷為假, 則返回false(!注:如果左邊表示式的值為0時,則返回0感謝@飛天鼠 的指正), 不管右邊的表示式是否為真.
- 如果左邊的表示式為真, 則繼續判斷右邊的表示式, 然後返回右邊表示式結果

這變得越來越有趣了,不是嗎?

Example 3:

不要這樣做:

function checkLogin(userName){
    if(userName){
        logIn(userName);
    }else{
        signUp();
    }
}

用這個代替:

function checkLogin(userName){
    userName && logIn(userName) || signUp();
}

解析
- 如果userName為真,則呼叫logIn函式並傳遞引數userName
- 如果userName為假或者logIn函式返回值為假(感謝@飛天鼠 的指正),則呼叫signUp函式

Example 4:

不要這樣做:

var user = {id:'this is id',log:'this is log'},
    userId;
if(user && user.log) {
    userId = user.id;
}else{
    userId = null;
}

用這個代替:

var user = {id:'this is id',log:'this is log'},
    userId;
userId = user && user.log && user.id;

解析
- 如果user為真, 則呼叫user.log, 並檢查user.log是否為真; 如果返回真, 則返回第三個表示式的返回值
- 如果user為空, 返回null

下圖為user.log存在的時候userId的值:
enter image description here
下圖為user.log不存在的時候userId的值 enter image description here

強大的立即呼叫函式表示式

(什麼是立即呼叫函式表示式, 何時使用它)
IIFE(Immediately Invoked Function Expressions, 發音:"Iffy")是立即呼叫函式表示式的縮寫形式, 它的語法大概如下:

(function () {
     // Do fun stuff​
})();

這是一個立即呼叫的匿名函式, 它在JavaScript中有一些特別重要的作用.

它是如何工作的?

  • 包圍匿名函式的一對括號會把它變成函式表示式或者變數表示式.
  • 這就相當於:

// 不帶括號:​
? = function () {};
​
​// 帶括號:​
(? = function () {});
​// 函式被一個不知名的變數引用了, 一對括號把它包圍了, 把它變成了一個匿名的函式表示式

同樣的, 我們甚至可以建立一個命名的立即呼叫函式表示式:

(showName = function (name) {console.log(name || "No Name")}) (); // No Name​
​
showName ("Rich"); // Rich​
showName (); // No Name
  • 記住, 當你不用var關鍵詞建立變數的時候, JavaScript會自動判斷該變數為全域性變數. 在上面的例子中是沒有必要使用var關鍵詞的(因為你之後可能會呼叫它).
  • 我們可以馬上或者在這之後使用這個函式
  • 但是我們不可以在之後呼叫匿名函式. 因為除非你建立匿名函式之後馬上呼叫, 在這之後沒有其他辦法可以引用它. 這是匿名函式只可以馬上呼叫它的原因.

  • 當把匿名函式包含在一對括號裡面時(字面量), 整個字面量會被運算,並且返回匿名函式的返回值. 它的返回值實質上是整個匿名函式自身, 所以我們只需要在這之後加上一對括號來馬上呼叫它.

  • 因此, 後面的一對括號等於告訴JavaScript編譯器馬上呼叫這個匿名函式, 所以它才會被稱之為"立即呼叫函式表示式".
  • 因為JavaScript基於函式塊的作用域規則, 在匿名函式內宣告變數都是區域性變數, 所以這些區域性變數沒辦法直接從外部獲取.
  • 就像其他函式一樣, 你可以向匿名函式設定引數和傳遞變數. 你可以根據這個特性, 利用匿名函式的作用域擴充套件它外圍函式的作用域(即閉包).

什麼時候應該使用它?

1.避免汙染全域性作用域
IIFE最廣泛的用途是避免汙染全域性作用域. 已經有很多JavaScript庫和JavaScript高手正在使用這種技巧, 尤其是在最流行jQuery外掛的開發者中. 你也應該把這個技巧應用在你的程式的主要檔案中(main.js).
在這個例子中, 我使用了匿名函式把所有全域性作用域的變數變成了區域性變數, 所以現在全域性作用域中還可以定義新的變數, 不用顧忌是否會和匿名函式內的變數在變數名上發生衝突(還包括其他庫或者框架):

// 所有的程式碼包含在立即呼叫函式中
(function () {

​var firstName = “Richard”;


function init () {

  doStuff (firstName);
  // 在這裡開始插入應用程式的程式碼...​

}

​
​function doStuff () {
  // Do stuff here​
}
​
​function doMoreStuff () {
 // Do more stuff here​
}
​
​// 啟動應用程式
init ();

}) ();

2.用作條件選擇器
這種使用方式還沒有被廣泛所知, 但它是相當強大的. 你可以不呼叫一個命名函式來處理複雜的運算的. 注意在三目運算子(.. ? .. : .. )中的兩個匿名函式, 我儘可能多地加入空白來使語句看起來更容易理解:

var unnamedDocs = [], 
    namedDocs = ["a_bridge_runover", "great_dreamers"];
​
​function createDoc(documentTitle) {
    var documentName = documentTitle 
​
        ?
​
 (function (theName) {
        var newNamedDoc = theName.toLocaleLowerCase().replace(" ", "_");
        namedDocs.push(newNamedDoc);
​
        return newNamedDoc;
    })(documentTitle);
​
​
        :
​
​
        (function () {
            var newUnnamedDoc = "untitled_" + Number(namedDocs.length + 1);
            unnamedDocs.push(newUnnamedDoc);
            return newUnnamedDoc;
        })();
​
​
    return documentName;
}
​createDoc("Over The Rainbow"); // over_the rainbow​
​createDoc(); // untitled_4

原文連結:12 Simple (Yet Powerful) JavaScript Tips
譯文連結:12個簡單(但強大)的JavaScript技巧
我的部落格:雲淡風輕

相關文章