1. 手写数组的 reduce 方法
Array.prototype.myReduce = function (fn, init) {
  if (typeof fn !== 'function') {
        throw new Error(`${fn} is not a function`)
    }
  // 当前 this 即为调用 myReduce 方法的数组
  let arr = this;
  let res, i;  // res 记录返回的值,i 为 当前数组下标
  if (init !== undefined) {  // 当传递了第二个参数,myReduce回调函数的第一个参数即为 init,第二个参数为数组的第一个元素
    res = init;
    i = 0;
  } else {  // 没有传递参数,默认第一个参数为数组的第一项,第二个参数为数组的第二个元素
    res = arr[0];
    i = 1;
  }
  for (; i < arr.length; i++) {
    res = fn(res, arr[i], i, arr);  // res 接收每一次循环 return 回来的值,作为下一次循环回调函数的第一个参数
  }
  return res;
}
2. 手写数组的 map 方法
// 手写 map方法
Array.prototype.myMap = function (fn, context) {
  if (typeof fn !== "function") {
    throw new Error(`${fn} is not a function`);
  }
  let arr = this;
  let res = [];
  context = context || window; //短路表达式,context有值则用,无值则为window
  for (let i = 0; i < arr.length; i++) {
    res.push(fn.call(context, arr[i], i, arr));
  }
  return res;
}