高阶函数
// 高阶函数
/* 
    1.一个函数的参数是一个函数
    2.一个函数的返回值也是一个函数
*/
/* 给业务代码扩展新功能 */
  function core(...args) {
    console.log("core", ...args);
  }
  Function.prototype.before = function (cb) {
    return (...args) => {
      cb();
      this(...args);
    };
  };
  let newCore = core.before(() => {
    console.log("before");
  });
  newCore(1, 2);
// 多个异步请求,同时获取最终结果
let fs = require("fs");
let obj = {};
const after = (times, callback) => {
  return function () {
    if (--times == 0) {
      callback(); // 当调用的次数到0的时候,就输出传入的callback,解决异步输出问题
    }
  };
};
let cb = after(2, () => {
  console.log(obj);
});
fs.readFile("./1.txt", "utf8", (err, data) => {
  obj.a = data;
  cb();
});
fs.readFile("./2.txt", "utf8", (err, data) => {
  obj.b = data;
  cb();
});
// 函数柯里化:让函数变得更具体些,如果两个请求,都回来之后才进行渲染。可以使用柯里化,等待两个请求回来在进行渲染
// 反柯里化:让函数变得范围更大一些
// 传入一个函数,返回一个函数,函数参数固定
// 如果函数没有到当前函数的参数个数,就返回一个新的函数,否则就直接返回结果
  function curring(fn) {
    const inner = (args = []) => { // 用args来储存每一次的结果
      return args.length >= fn.length
        ? fn(...args)  // 如果 >=length了,就直接返回原函数把参数传过去
        : (...userArgs) => inner([...args, ...userArgs]);  // 如果没有就把两次的参数存起来,然后返回一个新函数
    };
    return inner();
  }
  function sum(a, b, c, d) {
    return a + b + c + d;
  }
  let sum1 = curring(sum);
  let sum2 = sum1(1, 2);
  let sum3 = sum2(3);
  console.log(sum3(4)); // 10
  /* 用currying函数包装类型判断的方法 */
  function isType(typing, val) {
    return Object.prototype.toString.call(val) === `[object ${typing}]`;
  }
  let util = {};
  ["String", "Number", "Null", "Undefined", "Array", "Object"].forEach(
    (type) => {
      util[`is${type}`] = curring(isType)(type);
    }
  );
  console.log(util.isArray([])); // true