类似undersore的链式调用(下)

145 阅读2分钟

前言

上面一篇写了如何_(arr).unique(func)或者_.unique(arr, func)调用,这篇讲解如何真正的链式调用,类似arr.unique(func).map(mapf)

开启和结束链式调用

首先调用两个方法表示开始和结束链式调用,比如chain()开启链式调用,value()结束调用返回结果,类似

_(arr).chain().unique(func).map(mapf).value()
_.chain(arr).unique(func).map(mapf).value()

chain

  _.chain = function (obj) {
    let instance = _(obj); //通过之前的function 创建无new 化实例
    instance._chain = true; //确认链式调用,用于后面判断是否链式调用
    return instance;
  };

result

因为不是每一次调用都是链式调用,所以需要判断是否是链式调用,如果是则将结果储存起来,如果不是,则返回结果

  let result = function (instance, data) { 
    if (instance._chain) {
      instance.warp = data; //将返回的结果存入warp中,用于后面的计算取值
      return instance;
    }
    return data;
  };

接下来需要改造mixin方法,使之适用于链式调用和非链式调用

  _.mixin = function (obj) {
    _.each(_.functions(obj), function (key) {
      let func = obj[key];
      _.prototype[key] = function () {
        let args = [this.warp];
        Array.prototype.push.apply(args, arguments);
        return result(this, func.apply(this, args));
      };
    });
  };

value

最后则是返回结果

 //如果写成_.value 的话,最后结束链式调用的时候,还是会因为mixin而被认为是调用一个函数 最后return的还是result 中的instance
  _.prototype.value = function () {
    return this.warp;
  };

完整代码

(function (root) {
    var _ = function (obj) {
        if (!(this instanceof _)) {
            return new _(obj)  //无 new 实例
        }
        this.warp = obj
    }
    let result = function (instance, data) {
        //console.log(instance, data, 'result')
        if (instance._chain) {
            instance.warp = data
            return instance
        }
        return data
    }
    _.chain = function (obj) {
        //console.log(this, obj, 'chain')
        let instance = _(obj) //通过上面的function 无new化实例
        instance._chain = true //确定开始链式调用
        return instance
    }
    _.prototype.value = function () {
        //console.log(this, 'value')
        return this.warp
    }
    _.map = function (arr, callback) {
        return arr.map((item) => {
            return callback ? callback(item) : item
        })
    }
    //去重
    _.unique = function (arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            let target = callback ? callback(arr[i]) : arr[i]
            if (result.indexOf(target) === -1) {
                result.push(target)
            }
        }
        return result
    }
    _.max = function () { }
    _.each = function (arr, callback) {
        for (let i = 0; i < arr.length; i++) {
            //console.log(arr[i])
            callback(arr[i])
        }
    }
    _.functions = function (obj) {
        let arr = []
        for (const key in obj) {
            arr.push(key)
        }
        return arr
    }
    //_([123]).map(function(){})
    _.mixin = function (obj) {
        _.each(_.functions(obj), function (key) {
            let func = obj[key]
            _.prototype[key] = function () {
                let args = [this.warp]
                //数组合并
                //let arr=[].slice.call(arguments)
                //arr.forEach((item)=>{args.push(item)})
                //Array.prototype.push.apply(args, [1,2,3])
                Array.prototype.push.apply(args, arguments)//arguments 可以传递多个callback
                //func.apply(this, args)   //[数据,迭代器]
                return result(this, func.apply(this, args))
            }
        })
    }
    _.mixin(_)
    root._ = _
})(this)

好的,undersore的链式调用就结束了,如果有错误希望大佬指出,如果有更好的方法,也同样希望指教,谢谢。