1. 程式人生 > >函式柯里化 - 函式鏈式呼叫 - lazyman

函式柯里化 - 函式鏈式呼叫 - lazyman

實現鏈式呼叫實現 add函式,add(1)(2)(3)(4)輸出10,然後考慮拓展性

// 解析為add(1)返回函式A,A(2)返回函式B, B(3)返回函式C
function add(num) {
    var sum = 0;
    sum += num;
    return function(a) {
        sum += a;
        return functin(b) {
            sum += b;
            return function(c) {
                sum += c;
                return
sum; } } } }

但是如果鏈式呼叫加長,這種方法顯然不能滿足需求

// 改進
function add(num) {
    var sum = 0;
    sum += num;
    var func = function(param) {
        sum += param;
        return func;
    }
    return func;
}

// 這樣呼叫的結果返回的是一個函式的字串表示,那麼怎樣將結果輸出呢?
js中物件到原始值的轉換有兩種方法

當一個物件轉為原始值時,先檢視物件是否有valueOf方法,如果有且返回值為一個原始值,則直接返回該原始值,否則呼叫toString方法,返回字串表示

// 輸出數字型別的結果
function add(num) {
    var sum = 0;
    sum += num;
    var func = function(a) {
        sum += a;
        return func;
    }
    func.valueOf = function() {   // 函式結果輸出
        return sum;
    }
    func.toString = function() {
        return sum;
    }
    return func;
}

函式鏈式呼叫
實現函式的鏈式呼叫:util.chain(1).add(2).sum(3);

class utils {
    chain(a) {
        this.val = a;
        return this;
    }
    sum(b) {
        this.val += b;
        return this;
    }
    sub(c) {
        this.val -= c;
        return this;
    }
    value() {
        return this.val;
    }
}
var util = new utils();

實現lazyman

// lazyMan類的封裝
function _LazyMan(name) {
    this.taskList = [];  // 順序執行佇列
    var self = this;

    var fn = (function(n){
        var name = name;
        return function() {
            console.log('Hi! This is ' + name + '!');
            self.next();
        }
    })(name);

    this.taskList.push(fn);

    setTimeout(function(){
        self.next();
    }, 0);  // 延遲執行函式
}

_LazyMan.prototype.next = function() {
    var fn = this.taskList.shift();  // 獲取第一個函式執行
    fn && fn();
}
_LazyMan.prototype.eat = function(name) {
    var self = this;

    var fn = (function(n){
        return function() {
            console.log('Eat ' + name + '~');
            self.next();  // 鏈式呼叫,啟動下一個函式的執行
        }
    })(name);
    this.taskList.push(fn);
    return this;  // 實現鏈式呼叫
}
_LazyMan.prototype.sleep = function(time) {
    var self = this;

    var fn = (function(time){
        return function() {
            setTimeout(function() {
                console.log('Wake up after ' + time + 's!');
                self.next();
            }, time * 1000);
    })(time);
    this.taskList.push(fn);
    return this;
}
_LazyMan.prototype.sleepFirst = function(time) {
    var self = this;

    var fn = (function(time){
        return function() {
            setTimeout(function() {
                console.log('Wake up after ' + time + 's!');
                self.next();
            }, time * 1000);
    })(time);
    this.taskList.unshift(fn);
    return this;
}

// 最後的封裝
function LazyMan(name) {
    return new _LazyMan(name);
}