函数式编程学习概要

大纲

image.png

http://naotu.baidu.com/file/62bcbb1a539963f96bf3c5dcc515dbfa

curry函数

var curry = function curry(f) {
  //获取curry的参数,如果第二个参数不存在,则创建一个空数组
  var arr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  return function f1( ) {
    //获取当前函数的参数
    for (var len = arguments.length, args = Array(len), i = 0; i < len; i++) {
      args[i] = arguments[i];
    }
    //如果参数没有传完,合并arr和args,递归调用curry
    //f2函数其实是递归调用的终止条件,如果已经传完参数,执行函数并终止,否则递归curry
    return function f2(a) {
      return a.length === f.length ? f.apply(null, a) : curry(f, a);
    }([].concat(arr, args));//这种写法是将arr和args合并后作为f2函数的参数
  };
};

compose

<pre class="markdown-highlight" style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">简而言之:compose 可以把类似于 f(g(h(x))) 这种写法简化成 compose(f, g, h)(x)</pre>

const compose = (...args) => {  
    return x => {
    let re = args.pop()(x)
     return args.length? compose(...args)(re): re
    }
}

高阶函数

filter map forEach

<pre class="markdown-highlight" style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">高阶组件</pre>

1、减少冗余

2、配合修饰器减少代码

3、最小化原代码的改造幅度

npm 库 react-decoration,封装了很多高阶组件,可以直接配合decoration使用

@pureComponent

  validateClass(target, 'pureComponent');

  Object.setPrototypeOf(target.prototype, React.PureComponent.prototype);
  Object.setPrototypeOf(target, React.PureComponent);
}```

@debounce 

```export default function debounce(wait = 300, immediate = false) {
  return (target, key, descriptor) => {
    const userFunc = descriptor.value;

    validateFunction(userFunc, 'debounce');

    let timeout;

    return {
      ...descriptor,
      value: function debouncer(...params) {
        const callNow = immediate && !timeout;
        clearTimeout(timeout);

        timeout = setTimeout(() => {
          timeout = null;
          if (!immediate) {
            userFunc.apply(this, [...params]);
          }
        }, wait);

        if (callNow) {
          userFunc.apply(this, [...params]);
        }
      },
    };
  };
}```

@useShallowEqual

export function useShallowEqual(WrappedComponent) {
if (isFunction(WrappedComponent)) {
return (props, preProps)=>{
console.log(props, preProps);
return WrappedComponent(props);
};
} else {
class ShallowEqualEnhancer extends WrappedComponent {
shouldComponentUpdate(nextProps, nextState) {
let shouldUpdate = false;
if (!super.shouldComponentUpdate || super.shouldComponentUpdate(nextProps, nextState)) {
shouldUpdate = shallowEqual(this.props, nextProps, this.state, nextState);
}
return shouldUpdate;
}
}
ShallowEqualEnhancer.displayName = ShallowEqualEnhanced${WrappedComponent.displayName || WrappedComponent.name || 'Component'};

    return ShallowEqualEnhancer;
}

}