學習add(1)(2)(3)

實現add(1)(2)(3)

什麼是柯里化(Currying)

又稱部分求值(Partial Evaluation),簡單來講就是隻傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。javascript

你能夠這樣正規寫html

var sum = function (a, b) {
    return a + b;
}

固然用柯里化也能夠這樣java

var sumCurrying = function(a) {
    return function(b) {
        return a + b;
    }
}

var first = sum(1); //function
var second = sum(2); //function

sumCurrying(1)(2); //3
first(3); //4
second(4); //6

定義一個sumCurrying函數,接受一個參數並返回一個新的函數。調用sumCurrying函數以後,返回的函數就經過閉包的方式記住了sumCurrying的第一個參數。面試

可是這裏只能接受兩個參數,若是能接受不少個參數怎麼辦呢?閉包

柯里化的運用

function add () {
    var args = [].slice.call(arguments);

    var fn = function () {
        var arg_fn = [].slice.call(arguments);
        return add.apply(null, args.concat(arg_fn));
    }

    fn.valueOf = function() {
        return args.reduce((a, b) => a + b);
    }
    return fn;
}

我第一次看這個代碼的時候我也是納悶,what the fuck??valueOf是什麼鬼?它運行了嗎?看了原博主的我才明白了原來valueOf和toString在某些時候是會本身調用的,還牽扯到了類型轉換,啊啊啊啊~。app

來看看這個類型轉換的題函數

2 == [[[2]]] //是真仍是假?lua

解析:code

引用類型轉換爲基本類型(全部的引用類型轉換爲布爾值都是true)htm

  • 引用類型轉換爲字符串

1.優先調用toString方法(若是有),看其返回結果是不是原始類型,若是是,轉化爲字符串,返回。
2.不然,調用valueOf方法(若是有),看其返回結果是不是原始類型,若是是,轉化爲字符串,返回。
3.其餘報錯。

  • 引用類型轉化爲數字

1.優先調用valueOf方法(若是有),看其返回結果是不是原始類型,若是是,轉化爲數字,返回。
2.不然,調用toString方法(若是有),看其返回結果是不是原始類型,若是是,轉化爲數字,返回。
3.其餘報錯。

如下來自犀牛書:

1,null和undefined,相等。
2,數字和字符串,轉化爲數字再比較。
3,若是有true或false,轉換爲1或0,再比較。
4,若是有引用類型,優先調用valueOf。
5,其他都不相等。

回到類型轉換的這個題,由於是與數字進行比較,因此先調用valueOf(),返回的是自己不是原始類型,而後調用toString()獲得"2",而後變成了字符串和數字("2" == 2)進行比較。

因此結果爲 true

好,回到valueOf和toString被自動調用的問題上。

var obj = {name: 'Coco'};
var str = '123' + obj; 
console.log(str); //123[object Object]

爲何會這樣呢?上面的例子其實是

var obj = {name: 'Coco'};
var str = '123' + obj.toString();

固然咱們能夠改寫toString和valueOf方法

若是隻改寫 valueOf() 或是 toString()其中一個,會優先調用被改寫了的方法,而若是兩個同時改寫,則會像 Number 類型轉換規則同樣,優先查詢 valueOf() 方法,在 valueOf() 方法返回的是非原始類型的狀況下再查詢 toString() 方法。

var obj = {
    toString: function () {
        console.log('調用了toString');
        reutrn '1';
    },
    valueOf: function () {
        console.log('調用了vlaueOf');
        return '100';
    }
}

alert(obj + '1'); 
//調用了valueOf 
//'1001'

對於函數的valueOf來講:

function test () {
    var a = 1; 
    console.log(a);
}

test; 
//從新打印了一遍test函數體,實際上是自行調用調用了test.valueOf()
//若是valueOf返回的不是原始類型,那麼就會嘗試去找toString方法。

因此add(1)(2)

  • 首先進入add

  • 而後進入fn

  • 而後進入add

  • 調用valueOf

  • 3

參考資料:
一道面試題引起的javascript類型的轉換的思考

相關文章
相關標籤/搜索