• 浅谈JS的数组遍历方法


    用过Underscore的朋友都知道,它对数组(集合)的遍历有着非常完善的API可以调用的,_.each()就是其中一个。下面就是一个简单的例子:
    var arr = [1, 2, 3, 4, 5];
    _.each(arr, function(el) {
        console.log(el);
    });

    上面的代码会依次输出1, 2, 3, 4, 5,是不是很有意思,遍历一个数组连for循环都不用自己写了。_.each()方法遍历数组非常好用,但是它的内部实现一点都不难。下面就一起来看看到底是如何实现_.each()的。在这之前,我们先来看看_.each()的API。_.each()的一般是如下调用的:

    _.each(arr, fn, context);

    它接收3个参数,

    第一个是需要遍历的数组(其实是对象也是可以的,这个后面我们再一起来讨论);
    第二个是它的回调函数(这个回调函数可以传入3个参数,如:function(el, i, arr),分别是当前元素、当前索引和原数组);
    第三个是回调函数需要绑定到的上下文,即指定回调函数fn的this值。
     
    好啦,需求已经非常明确了,开始干活啦!
    我们先来实现一个最简单的_.each(),它不能够修改上下文this的,接收两个参数,代码如下:
     
    var _ = {}; // 假设这就是underscore哈
     
    // 一个最简单的_.each方法的实现
    _.each = function(arr, fn) {
      for(var i = 0; i < arr.length; i++) {
        fn(arr[i], i, arr);
      }
      return arr; // 把原数组返回
    }

    怎么样?是不是很简单呢?只是用一个for循环,不停的调用回调函数即可,短短几行代码就搞定了,相信没有朋友看不懂的哈!下面我们来测试一下看能不能正常工作:

    var arr = [1, 2, 3, 4, 5];
    _.each(arr, function(el, i, arr) {
      console.log(el);
    });

    在浏览器打开,然后控制台就会看到有正确的输出了。

    这么简单的代码一点意思也没有,接下来看一个比较有点挑战性的例子哈。比如,数组arr有个sum属性,我们需要把数组所有的元素求和之后存放到sum里面,如下:
    var arr = [1, 2, 3, 4, 5];
    arr.sum = 0; // sum属性用来存放数组元素之和
    _.each(arr, function(el, i, arr) {
      this.sum += el;
    });

    这时候,回调函数里面用到了this,如果不绑定的话,this默认就是window,这不是我们想要的,我们希望它绑定到数组arr上面。call或者apply可以实现这个功能,代码如下:

    var _ = {}; // 假设这就是underscore哈
     
    // bind,接收两个参数fn和context
    // 把fn绑定到context上面
    var bind = function(fn, context) {
      context = context || null;
      return function(el, i, arr) {
        fn.call(context, el, i, arr);
      }
    }
     
    // _.each
    _.each = function(arr, fn, context) {
     
      // 调用bind方法,把fn绑定到context上面
      fn = bind(fn, context);
     
      for(var i = 0; i < arr.length; i++) {
        fn(arr[i], i, arr);
      }
      return arr;
    }
     
     
    // 测试用例:
    var arr = [1, 2, 3, 4, 5];
    arr.sum = 0; // sum属性用来存放数组元素之和
     
    _.each(arr, function(el, i, arr) {
      this.sum += el;
    }, arr);
     
    console.log(arr.sum); // 15

    好啦,这个_.each()已经足够强大了,可以正常遍历数组,还可以任意指定this值改变回调函数的上下文。但是,我们前面有提到过,Underscore的_.each()还可以遍历对象的 ,这个实现也不难,只要判断一下传入的第一个参数是对象还是数组,如果是数组就像我们一样遍历,否则如果是对象,使用对象的for...in循环遍历就行了。有兴趣的可以自己试试,或者看看underscore的源码。

    注意:自从ES5标准以来,原生数组就已经具有了Array.prototype.forEach、Array.prototype.Map等遍历方法了,在项目中可以使用原生的。
     
     
     
  • 相关阅读:
    从 0 配置 webpack(一)
    Redux
    React Hooks 全解(二)
    日本人要把核污水排进大海,我突然想到几个问题
    突然发现,我的代码还花花绿绿的,挺好看的
    Ghidra ,改道吧,我也准备改道这玩意了
    语音控制?这,看起来很眼熟。
    winafl 工具的编译
    关于 TX 的 WeGame 的一点疑问
    新年的第一个随笔,随便写写吧
  • 原文地址:https://www.cnblogs.com/yugege/p/5584672.html
Copyright © 2020-2023  润新知