深入浅析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等遍历方法了,在项目中可以使用原生的。

以上所述是小编给大家介绍的深入浅析JS的数组遍历方法(推荐)的全部叙述,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 详谈js遍历集合(Array,Map,Set)

    Array可以使用下标,Map和Set不能使用下标,ES6引入了iterable类型,Array,Map,Set都属于iterable类型,它们可以使用for...of循环来遍历: var a = ['A', 'B', 'C']; var s = new Set(['A', 'B', 'C']); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); for (var x of a) { // 遍历Array alert(x); } for (var

  • js Map List 遍历使用示例

    Map (exMap:{"name":"abc","sex",'male'}): 在不知道key的情况下遍历map: 网上说过这种方法: 复制代码 代码如下: for(var key in exMap){ Console.write("key:"+key+";value:"+exMap[key]);//经我考证,the key is undefined.So the method is not right.

  • js遍历子节点子元素附属性及方法

    复制代码 代码如下: // 添加子节点前 删除所有子节点 var usernameEle = document.getElementById("username"); var childs = usernameEle.childNodes; for(var i = childs.length - 1; i >= 0; i--) { usernameEle.removeChild(childs[i]); } var username = document.createTextNod

  • 深入浅析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()方法遍历数组非常好用,但是它的内部实现一点都不难.下面就一起来看看到底是如何实现_

  • 原生JS查找元素的方法(推荐)

    今天写了一个很简单.很粗暴的通过JS根据类来查找DOM元素. 为了降低它的粗暴等级(耗费性能)我给了三个等级. 首先性能最好的,适合FF,CH,IE8,通过querySelectorAll这个API. 其次是指定ID 最后只能全页面进行匹配class,不过比较节省的性能的是,在指定class名称的时候,同时传入HTML标签的类型,用于节省遍历的范围! 因为水平有限,目前也只能写成这种,真的好好奇JQ的选择器是怎么去匹配DOM的,如果有大神看到这篇文章,请不要吝啬施教... 下面贴代码: func

  • PHP多维数组遍历方法(2种实现方法)

    本文实例讲述了PHP多维数组遍历方法.分享给大家供大家参考,具体如下: 方法一: $a=array('fruits'=>array('a'=>'orange', 'b'=>'grape',c=>'apple'), 'numbers'=>array(1,2,3,4,5,6), 'holes'=>array('first',5=>'second','third') ); foreach($a as $list=>$things){ if(is_array($th

  • xcode中获取js文件的路径方法(推荐)

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"click" ofType:@"js"]; 理论上这样是应该能获取click.js的路径的,但是返回的确是null. 解决方法是: 项目的TARGETS-->Build Phases 在Compile Sources中 ,去掉你的js文件 在Copy Bundle Resources中,加上你的js文件 原理应该就是改之前Xcode默认把

  • JS的数组迭代方法

    本文实例讲述了JS的数组迭代方法.分享给大家供大家参考.具体实现方法如下: <!doctype html> <html> <head lang="zh"> <meta charset="utf-8"> <title>js数组迭代</title> <meta name="renderer" content="webkit"> <script

  • JS实现数组去重方法总结(六种方法)

    方法一: 双层循环,外层循环元素,内层循环时比较值 如果有相同的值则跳过,不相同则push进数组 Array.prototype.distinct = function(){ var arr = this, result = [], i, j, len = arr.length; for(i = 0; i < len; i++){ for(j = i + 1; j < len; j++){ if(arr[i] === arr[j]){ j = ++i; } } result.push(arr[

  • 详解vue数组遍历方法forEach和map的原理解析和实际应用

    一.前言 forEach和map是数组的两个方法,作用都是遍历数组.在vue项目的处理数据中经常会用到,这里介绍一下两者的区别和具体用法示例. 二.代码 1. 相同点 都是数组的方法 都用来遍历数组 两个函数都有4个参数:匿名函数中可传3个参数item(当前项), index(当前项的索引), arr(原数组),还有一个可选参数this 匿名函数中的this默认是指向window的 对空数组不会调用回调函数 不会改变原数组(某些情况下可改变) 2. forEach (1) 没有返回值. var

  • 深入浅析JS是按值传递还是按引用传递(推荐)

    按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本.修改形参的值并不会影响实参. 按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本.这意味着函数形参的值如果被修改,实参也会被修改.同时两者指向相同的值. 按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG. 按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低.两种传值方式都有各自的问题. JS的基本类型,是按值传递的. var a = 1

  • PHP 数组遍历方法大全(foreach,list,each)

    在PHP中数组分为两类: 数字索引数组和关联数组. 其中数字索引数组和C语言中的数组一样,下标是为0,1,2- 而关联数组下标可能是任意类型,与其它语言中的hash,map等结构相似. 下面介绍PHP中遍历关联数组的三种方法: 方法1:foreach 复制代码 代码如下: <?php $sports = array( 'football' => 'good', 'swimming' => 'very well', 'running' => 'not good'); foreach

  • php若干单维数组遍历方法的比较

    复制代码 代码如下: <?php //a $arr=array('a'=>'abc','b'=>123,'c'=>true); //b //$arr=range('a','d'); //1 for($i=0;$i<sizeof($arr);$i++) echo $arr[$i].', '; echo '<br />'; //2 foreach($arr as $key) echo "$key, "; echo '<br />'; /

随机推荐