惰性求值,面向对象

个人理解,所谓惰性求值,就是将所有的方法用数组存储起来,遇到一个开始计算的标志时,再遍历数组,执行方法。

1.第一种方式:面向对象的方法

  // 惰性求值
  const _lazy = (function () {
    const MAX_ARRAY_LENGTH = 100;
    const LAZY_FILTER_FLAG = 1;
    const LAZY_MAP_FLAG = 2;
    LazyWrapper.prototype.filter = filter;
    LazyWrapper.prototype.take = take;
    LazyWrapper.prototype.value = lazyValue;
    LazyWrapper.prototype.map = map;

    function LazyWrapper(value) {
      this.__wrapped__ = value; // 存储数据
      this.__iteratees__ = []; // 存储方法,便于后期迭代操作
      this.__takeCount__ = MAX_ARRAY_LENGTH;
    }

    function lazy(value) {
      return new LazyWrapper(value);
    }

    function filter(iteratee) {
      this.__iteratees__.push({
        'iteratee': iteratee,
        'type': LAZY_FILTER_FLAG
      });
      return this;
    }

    function map(iteratee) {
      this.__iteratees__.push({
        'iteratee': iteratee,
        'type': LAZY_MAP_FLAG
      });
      return this;
    }

    function take(n) {
      this.__takeCount__ = n;
      return this;
    }

    function lazyValue() {

      const takeCount = this.__takeCount__; // 需要得到的数据个数
      const iteCount = this.__iteratees__; // 存储的方法个数
      const handleValue = this.__wrapped__; // 待处理的数据
      const result = []; // 存储符合要求的数据
      let resIndex = 0;

      checkj: // 语句标签
        for (let i = resIndex; result.length < takeCount && i < handleValue.length; i++) {
          const value = handleValue[i];
          for (let j = 0; j < iteCount.length; j++) {
            if (iteCount[j].type === 1) {
              const computed = iteCount[j].iteratee(value); // 每个方法都要调用处理
              if (!computed) { // 如果不符合要求,则继续下一个数据
                continue checkj; // 退出当前循环
              }
            }
          }
          result[resIndex++] = value;
        }

      for (let j = 0; j < result.length; j++) {
        const value = result[j];
        for (let k = 0; k < iteCount.length; k++) {
          if (iteCount[k].type === 2) {
            result[j] = iteCount[k].iteratee(value);
          }
        }
      }
      return result;
    }

    return lazy;
  })();

总结:

  • 用立即执行函数,封装性更好,不污染全局作用域,同时,外界无法访问其内部方法。
  • 利用了原型模式和构造函数模式。

2.第二种:es6的代理Proxy

实现函数名的链式使用

    const pipe = (function () {
      return function (value) {
        const funcStack = [];
        const oproxy = new Proxy({}, {
          /**
           *
           * @param pipeObject 目标对象
           * @param fnName     属性名
           */
          get : function (pipeObject ,fnName) {
            if (fnName === 'get') {
              /**
               * val 为累加器
               */
              return funcStack.reduce((val, fn) => {
                return fn(val);
              }, value);
            }
            funcStack.push(window[fnName]);
            return oproxy;
          }
        });
        return oproxy;
      }
    }());
    // 这里必须是var声明的变量,因为变量是可以挂载在window对象上的。
    // 用es6的let和const,window[fnName]为undefined
    var double = n => n * 2;
    var pow    = n => n * n;
    var reverseInt = n => n.toString().split("").reverse().join("") | 0;
    console.log(pipe(3).double.pow.reverseInt.get);

总结:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值