从Polyfill(或源码)中看map(),forEach(),

2019-01-13  本文已影响0人  罗坤_23333

目录

map()循环返回新数组

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

简化:

Array.prototype.map = function(callback){
  //创建一个length值为原数组长度的新数组A
  var A = new Array(this.length);
  
  var k = 0;
  //前测试循环语句,在循环前就会对出口条件求值
  while(k<this.length){
    var kValue;
    kValue = this[ k ];
    //传入的callback参数被赋值给了数组A对应的索引
    A[ k ] = callback(kValue, k);

    k++;
  }

  //返回这个新数组A
  return A;
}

//eg:
console.log([0,1,2,3].map((item,index)=>{
  return item+1;
}))
// [1,2,3,4]

知识点梳理:

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<this.length){
    var kValue;
    kValue = this[ k ];
    //accumulator开始累加
    accumulator= callback(accumulator, kValue ,this);

    k++;
  }

  //返回这个累加器
  return accumulator ;
}

//eg:
//0+1+2+3
console.log([0,1,2,3].map((accumulator,currentValue,originalArr)=>{
    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手动退出循环

参考

上一篇下一篇

猜你喜欢

热点阅读