es6_proxy

发布时间 2024-01-02 19:50:52作者: 苏沐问

Es6_proxy习题讲解

概述

这是对于es6中的proxy部分中的一道题做讲解,因为其晦涩难懂,所以单独抽出来做解释,方便以后复习的时候能快速的过,而不用重新想破脑袋。


解析

var pipe = function (value) {
  var funcStack = [];
  var oproxy = new Proxy({} , {
    get : function (pipeObject, fnName) {
      if (fnName === 'get') {
        return funcStack.reduce(function (val, fn) {
          return fn(val);
        },value);
      }
      funcStack.push(window[fnName]);
      return oproxy;
    }
  });
  return oproxy;
}
var double = n => n * 2;
var pow    = n => n * n;
var reverseInt = n => n.toString().split("").reverse().join("") | 0;
pipe(3).double.pow.reverseInt.get; // 63

上述代码可以分成三部分,分别是代理部分,函数定义部分,和调用部分,我将针对这三部分按照最能让人理解的顺序进行讲解。


函数定义部分

var double = n => n * 2;
var pow    = n => n * n;
var reverseInt = n => n.toString().split("").reverse().join("") | 0;

double和pow函数意思很明确,不需要过多的解释,但是reverseInt函数可以稍微解释一下。

reverseInt函数做了两件事情。第一,将字符串反转,第二,将字符串类型变成数字类型。

其中|0 起的作用就是将字符串类型转成数字类型。


代理部分

var pipe = function (value) {
  var funcStack = [];
  var oproxy = new Proxy({} , {
    get : function (pipeObject, fnName) {
      if (fnName === 'get') {
        return funcStack.reduce(function (val, fn) {
          return fn(val);
        },value);
      }
      funcStack.push(window[fnName]);
      return oproxy;
    }
  });
  return oproxy;
}

首先,pipe是一个函数,我们调用pipe函数的时候会传入一个值value,最终函数调用的返回值是一个代理对象oproxy。

在pipe函数中我们定义了一个数组funcStack,用于存放我们函数定义部分定义的函数,这里需要注意一个问题,数组funcStack不是栈而是数组,例如funcStack.push(1,2,3),我们输出的funcStack数组值为[1,2,3],并不是[3,2,1]。这里做出说明是因为涉及到后面的函数调用顺序的问题,因此特意说明一下。


代理对象oproxy,它给一个空对象 {} 设置了代理,其代理逻辑为,若是调用代理对象的属性名不为 "get" ,则执行下面的代码。

funcStack.push(window[fnName]);
return oproxy;

window[fnName]根据字符串 fnName 来获取全局对象中具有相应名称的函数,并将其push到数组funcStack中,然后返回代理对象oproxy。


若是调用代理对象的属性名为 "get" ,则执行下面的代码。

return funcStack.reduce(function (val, fn) {
	return fn(val);
},value);

funcStack.reduce方法中回调函数function (val, fn) {return fn(val);}以value作为初始值赋值给val,fn为当前数组funcStack中正在调用的值(因为数组funcStack中全为函数,所以相当于调用函数),然后执行fn(val)所得的值赋值给累加器val用于下一轮的调用。


调用部分

pipe(3).double.pow.reverseInt.get;//63

综上所述,调用部分做的事情就是,以3作为初始值,分别调用double函数、pow函数和reverseInt函数,前一轮函数计算的值用在后一轮函数的计算之上,最终得出结果。

计算过程如下:

  1. double(3) = 6
  2. pow(6) = 36
  3. reverseInt(36) = 63