美文网首页
从Polyfill(或源码)中看map(),forEach(),

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

作者: 罗坤_23333 | 来源:发表于2019-01-13 22:46 被阅读0次

    目录

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

    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]
    

    知识点梳理:

    • 在只知道数组要保存的项目数量情况下,可以使用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<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手动退出循环

    参考

    相关文章

      网友评论

          本文标题:从Polyfill(或源码)中看map(),forEach(),

          本文链接:https://www.haomeiwen.com/subject/rctrdqtx.html