从Polyfill(或源码)中看map(),forEach(),reduce()三者区别

目录

  • map()
  • forEach()
  • reduce()
  • 三者区别

map()循环返回新数组

更加工程化的Polyfill代码:Array.prototype.map()

简化:

Array.prototype.map = function(callback){
  //创建一个length值为原数组长度的新数组A
  var A = new Array(this.length);
  
  var O = Object(this); //强制转对象,为后续in操作符做准备
  var k = 0;
  //前测试循环语句,在循环前就会对出口条件求值
  while(k{
  return item+1;
}))
// [1,2,3,4]

知识点梳理:

  • 在只知道数组要保存的项目数量情况下,可以使用Array构造函数创建数组,而该数值会自动变成length属性的值
  • 使用while前测试循环语句,适用于在循环次数不易预知的情况

map的第二个参数

arr.map(callback[, thisArg])
执行 callback 函数时值被用作this

//传入的callback参数被赋值给了数组A对应的索引
A[ k ] = callback.call(thisArg, kValue, k);

forEach()遍历数组,并将元素传递给回调函数

更加工程化的Polyfill代码:Array.prototype.forEach()

简化:

Array.prototype.forEach= function(callback){
  var k = 0;
  while(k < this.length){
    var kValue;
    kValue = this[ k ];
    this[ k ] = callback(kValue, k);
    
    k++;
  }

   //这里是默认返回undefined
   //return undefined
}

//eg:
var arr = [0,1,2,3];
console.log(a.forEach((item,index)=>{
  return item+1;
}))  // undefined

console.log(arr)  // [0,1,2,3]

readuce()累加器

更加工程化的Polyfill代码:Array.prototype.reduce()

简化:

Array.prototype.reduce= function(callback){
  //新建一个栈内存用于存储累加
  var accumulator;
  var k = 0;

  //使用reduce时,回调函数callback共2个必填参数(accumulator和当前索引所在值)
  //和1个非必填参数(原数组)
  if (arguments.length >= 2) {
          value = arguments[1];
      } else {
          while (k < this.length && !(k in this)) {
              k++;
          }

            // 3. If len is 0 and initialValue is not present,
            //    throw a TypeError exception.
          if (k >= this.length) {
              throw new TypeError( 'Reduce of empty array ' +
                  'with no initial value' );
          }
          value = this[k++];
    }

  while(k{
    return accumulator+currentValue
})) //6

案例:使用reduce和Promise实现事件列队[1]

设计一个简单的任务队列,要求分别在1,3,4秒后打印出”1“,”2“,”3“

new Queue()
        .task(1000, () => {
            console.log(1)
        })
        .task(2000, () => {
            console.log(2)
        })
        .task(1000, () => {
            console.log(3)
        })
        .start()

function Queue(){
  this.event_list = [];  //事件队列
  this.task = function(duration, callback){
    // 保证队列中所有事件都为Promise对象
    var event_item = new Promise((resolve)=>{
      setTimeout(()=>{
          callback.bind(this)
          resolve()
      },duration)
    })
    event_list.push(event_item)  //添加事件
    // 返回当前实例实现链式调用
    return this;
  }
  this.start = function(){
    this.event_list.reduce(
        //初始值, 或者计算结束后的返回值
        //每次 reduce 返回的值都会作为下次 reduce 回调函数的第一个参数,
        //直到队列循环完毕,因此可以进行累加计算。
        (previousPromise, nextPromise) => previousPromise.then(() => nextPromise()),  
        Promise.resolve() //当前元素
    )
  }
}

map()forEach()reduce()区别:

方法 map() forEach() reduce()
原数组 永远不变 永远不变 永远不变
原数组各索引上的值 永远不变 可能改变 永远不变
返回值 船新数组 永远undefined callback()决定

ps: 可能改变如果传入的callback会对item进行值改变并返回新值

其他

  • 上述三种循环无法使用return false或者break手动退出循环,除了抛出异常以外
  • 数组(稀疏数组)中对于那些已经被删除或者从未被赋值的索引不会被执行callback
     var arr = [0, 1, 2];
     arr[10] = 11;
     var arr2 = arr.map(function(x){
       return x === undefined
     });
    
    console.log(arr2); // []
    

参考

  • [1] 为什么要使用reduce()来解决Promises执行顺序
  • [2] 如何理解reduce()? - 翻译

你可能感兴趣的:(从Polyfill(或源码)中看map(),forEach(),reduce()三者区别)