1. 程式人生 > >Underscore.js 學習(四)— Functions

Underscore.js 學習(四)— Functions

因為underscore本來就是為了充分發揮JavaScript的函數語言程式設計特性,所以也提供了大量JavaScript本身沒有的高階函式。

partial

partial()就是為一個函式建立偏函式。

假設我們要計算xy,這時只需要呼叫Math.pow(x, y)就可以了。

假設我們經常計算2^y,每次都寫Math.pow(2, y)就比較麻煩,如果建立一個新的函式能直接這樣寫pow2N(y)就好了,這個新函式pow2N(y)就是根據Math.pow(x, y)創建出來的偏函式,它固定住了原函式的第一個引數(始終為2):

'use strict';

var pow2N = _.partial(Math
.pow, 2); pow2N(3); // 8 pow2N(5); // 32 pow2N(10); // 1024

如果我們不想固定第一個引數,想固定第二個引數怎麼辦?比如,希望建立一個偏函式cube(x),計算x^3,可以用_作佔位符,固定住第二個引數:

'use strict';

var cube = _.partial(Math.pow, _, 3);
cube(3); // 27
cube(5); // 125
cube(10); // 1000

可見,建立偏函式的目的是將原函式的某些引數固定住,可以降低新函式呼叫的難度。

memoize

如果一個函式呼叫開銷很大,我們就可能希望能把結果快取下來,以便後續呼叫時直接獲得結果。舉個例子,計算階乘就比較耗時:

'use strict';

function factorial(n) {
    console.log('start calculate ' + n + '!...');
    var s = 1, i = n;
    while (i > 1) {
        s = s * i;
        i --;
    }
    console.log(n + '! = ' + s);
    return s;
}

factorial(10); // 3628800
// 注意控制檯輸出:
// start calculate 10!...
// 10! = 3628800

用memoize()就可以自動快取函式計算的結果:

'use strict';

var factorial = _.memoize(function(n) {
    console.log('start calculate ' + n + '!...');
    var s = 1, i = n;
    while (i > 1) {
        s = s * i;
        i --;
    }
    console.log(n + '! = ' + s);
    return s;
});

// 第一次呼叫:
factorial(10); // 3628800
// 注意控制檯輸出:
// start calculate 10!...
// 10! = 3628800

// 第二次呼叫:
factorial(10); // 3628800
// 控制檯沒有輸出

對於相同的呼叫,比如連續兩次呼叫factorial(10),第二次呼叫並沒有計算,而是直接返回上次計算後快取的結果。不過,當你計算factorial(9)的時候,仍然會重新計算。

可以對factorial()進行改進,讓其遞迴呼叫:


'use strict';

var factorial = _.memoize(function(n) {
    console.log('start calculate ' + n + '!...');
    if (n < 2) {
        return 1;
    }
    return n * factorial(n - 1);
});

factorial(10); // 3628800
// 輸出結果說明factorial(1)~factorial(10)都已經快取了:
// start calculate 10!...
// start calculate 9!...
// start calculate 8!...
// start calculate 7!...
// start calculate 6!...
// start calculate 5!...
// start calculate 4!...
// start calculate 3!...
// start calculate 2!...
// start calculate 1!...

factorial(9); // 362880
// console無輸出

once

顧名思義,once()保證某個函式執行且僅執行一次。如果你有一個方法叫register(),使用者在頁面上點兩個按鈕的任何一個都可以執行的話,就可以用once()保證函式僅呼叫一次,無論使用者點選多少次:

var register = _.once(function () {
    alert('Register ok!');
});

// 測試效果:
register();
register();
register();

delay

delay()可以讓一個函式延遲執行,效果和setTimeout()是一樣的,但是程式碼明顯簡單了:

'use strict';

// 2秒後呼叫alert():
_.delay(alert, 2000);