内容要点:

ES5中定义了9个新的数组方法来遍历、映射、过滤、检测、简化和搜索数组。

概述:首先,大多数方法的第一个参数接收一个函数,并且对数组的每个元素(或一个元素)调用一次该函数。

如果是稀疏数组,对不存在的元素不调用传递的函数。

在大多数情况下,调用提供的函数使用三个参数:数组元素、元素的索引和数组本身。

通常,只需要第一个参数值,可以忽略后两个参数。大多数ES5数组的方法的第一个参数是一个函数,第二个参数是可选的。如果有第二个参数,则调用的函数被看做是第二个参数的方法。

也就是说,在调用函数时传递进去的第二个参数作为它的this关键字的值来使用。

被调用的函数的返回值非常重要,但是不同的方法处理返回值的方法也不一样。ES5中的数组方法都不会修改它们调用的原始数值。

当然,传递给这些方法的函数是可以修改这些数组的。

一.forEach()

forEach()方法从头至尾遍历数组,为每个元素调用指定的函数。

如上所述,传递的函数作为forEach()的第一个参数。然后forEach()使用三个参数调用该函数:数组元素、元素的索引和数组本身,

如果只关心数组元素的值,可以编写只有一个参数的函数--额外的参数将忽略:

var data = [1,2,3,4,5];  //要求和的数组

//计算数组元素的和值

var sum = 0;   //初始为0

data.forEach(function(value){ sum+=value; });  //将每个值累加到sum上

sum   //=>15

//每个数组元素的值自加1

data.forEach(function(v,i,a){ a[i] = v + 1; })

data             //=>[2,3,4,5,6]

注意,forEach()无法在所有元素都传递给调用的函数之前终止遍历。

也就是说,没有像for循环中使用的相应的break语句。如果要提前终止,必须把forEach()方法放在一个try块中,并能抛出一个异常。

如果forEach()调用的函数抛出foreach.break异常,循环会提前终止。

function foreach(a,f,t){

try{ a.forEach(f,t); }

catch(e){ if( e ===foreach.break )  return;

else throw e;

}

}

foreach.break = new Error("StopIteration");

二.map()

map()方法将调用的数组的每个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值。

例如,

a = [1,2,3];

b = a.map(function(){ return x*x }); //b是[1,4,9]

传递给map()的函数的调用方法给forEach()的函数的调用方式一样。但传递给map()的函数应该有返回值。注意,map()返回的是新数组:它不修改调用的数组。

如果是稀疏数组,返回的也是相同方式的稀疏数组:它具有相同的长度,相同的缺失元素。

三.filter()

filter()方法返回的数组元素是调用的数组的一个子集。

传递的函数是用来逻辑判断的:该函数返回true或false。调用判断函数就像调用forEach()和map()一样。

如果返回值为true或能转化为true的值,那么传递给判定函数的元素就是这个子集的成员,它将被添加到一个作为返回值的数组中。

例如:

a = [5,4,3,2,1];

smallvalues = a.filter( function(x) { return x<3 } ); //[2,1]

everyother = a.filter( function(x,i){ return i%2==0 } ); //[5,3,1]

注意,filter()会跳过稀疏数组中缺少的元素,它的返回值总是稠密的,为了压缩稀疏数组的空缺,代码如下:

var dense = sparse.filter( function(){ return true; } );

甚至,压缩空缺并删除undefined和null元素,可以这样使用filter():

a = a.filter( function(x) { return x !== undefined && x!=null; } );

四.every()和some()

every()和some()方法是数组的逻辑判定:它们对数组元素应用指定的函数进行判定,返回true或false。

every()方法就像数学中的 "针对所有" 的量词:当且仅当针对数组中的所有元素调用判断函数都返回true,它才返回true:

a = [1,2,3,4,5]

a.every( function(x) { return x <10; } )  //=>true,

a.every( function(x) { return x%2===0; } ) //=>false:不是所有的值都是偶数

some()方法就像数学中的"存在"的量词:当数组中至少有一个元素调用判定函数返回true,它就返回true;并且当且仅当数值中的所有元素调用判断函数都返回false,它才返回false:

a = [1,2,3,4,5];

a.some( function(x){ return x%2===0; } ) //=>true

a.some(isNaN)   //=>false:a不包含非数组元素

五.reduce()和reduceRight()

reduce()和reduceRight()方法使用指定的函数将数组元素进行组合,生成单个值。这在函数式编程中是常见的操作,也可以称为"注入"和"折叠"。

例如:

var a = [1,2,3,4,5];

var sum = a.reduce( function(x,y) { return x+y },0 ); //数组求和

var  product = a.reduce( function(x,y){ return x*y },1  ); //数组求积

var max = a.reduce( function( x,y ){ return (x>y)?x:y; } ); //求最大值

reduce()需要两个参数。第一个是执行化简操作的函数。化简函数的任务就是用某种方法把两个值组合或化简为一个值,并返回化简后的值。

在上述例子中,函数通过加法、乘法或取最大值的方法组合两个值。第二个(可选)参数是一个传递给函数的初始值。

reduce()使用的函数与forEach()和map()使用的函数不同。比较熟悉的是:

数组元素的索引和数组本身将作为第2-4个参数传递给函数。

第一个参数是到目前为止的化简操作积累的结果。第一次调用函数时,第一个参数就是初始值,它就是传递reduce()的第二个参数。在接下来的调用中,这个值就是上一次化简函数的返回值。

在上面的第一个例子中,第一次调用化简函数时的参数是0和1.将两者相加并返回1.再次调用时的参数是1和2,它返回3.

然后计算3+3=6、6+4=10,最后计算10+5=15.最后的值是15,reduce()返回这个值。

上面第三次调用reduce()时只有一个参数:没有指定初始值。当不指定初始值调用reduce()时,它将使用数组的第一个元素作为其初始值。

当不指定初始值调用reduce()时,它将使用数组的第一个元素作为其初始值。这意味着第一次调用化简函数就使用了第一次和第二个数组元素作为其第一个和第二个参数。在上面求和与求积德例子中,可以省略初始化参数。

在空数组上,不带初始值参数调用reduce()将导致类型错误异常。如果调用它的时候只有一个值--数组只有一个元素并且没有指定初始值,或者有一个空数组并且指定一个初始值--reduce()只是简单地返回那个值而不会调用化简函数。

reduceRight()的工作原理和reduce()一样,不同的是它按照数组索引从高到低(从左到右)处理数组,而不是从低到高。

如果化简操作的优化顺序是从右到左,你可能想使用它,例如:

var a = [2,3,4];

//计算2^(3^4).乘方操作的优先顺序是从右到左

var big = a.reduceRight( function( accumulator,value ){ return Math.pow(value,accumulator); } );

注意,reduce()和reduceRight()都能接收一个可选的参数,它指定了化简函数调用时的this关键字的值。可选的初始值参数仍然需要占一个位置。

值得注意的是,上面描述的every()和some()方法是一种类型的数组化简操作。但是不同的是,它们会尽早终止遍历而不总是访问每一个数组元素。

当两个对象拥有同名的属性时,union()函数使用第一个参数的属性值。这样,reduce()和reduceRight()在使用union()时给出了不同的结果。

var objects = [{x:1,a:1},{y:2,a:2},{z:3,a:3}];

var leftunion = objects.reduce( union ); //{ x:1,y:2,z:3,a:1 }

var rightunion = objects.reduceRight( union );  //{ x:1,y:2,z:3,a:3 }

六.indexOf()和lastIndexOf()

indexOf()和lastIndexOf()搜索整个数组具有给定值的元素,返回找到的第一个元素的索引或者如果没有找到就返回-1.indexOf()从头至尾搜索,而lastIndexOf()则反向搜索。

a = [0,1,2,1,0];

a.indexOf(1)  //=>:a[1]是1

a.lastIndexOf(1) //=>3:a[3]是1

a.indexOf(3) //=>-1:没有值为3的元素

不同于本节描述的其他方法,indexOf()和lastIndexOf()方法不接收一个函数作为其参数。

第一个参数是需要搜索的值,第二个参数是可选的:它指定数组中的一个索引,从那里开始搜索。如果省略该参数,indexOf()从头开始搜索,而lastIndexOf()从末尾开始搜索。

第二个参数也可以是负数,它代表相对数组末尾的偏移量,对于splice()方法:例如,-1指定数组的最后一个元素。

如下函数在一个数组中搜索指定的值并返回包含所有匹配的数组索引的一个数组。

//在数组中查找所有出现的x,并返回一个包含匹配索引的数组

function findall(a,x){

var results = [];   //将会返回的数组

len = a.length, //待搜索数组的长度

pos = 0; //开始搜索的位置

while( pos < len ){

pos = a.indexOf(x,pos); //搜索

if(pos===-1) break;

results.push(pos);      //否则,在数组中存储索引

pos = pos+1;            //并从下一个位置开始搜索

}

return results;                   //返回包含索引的数组

}

《JS权威指南学习总结--7.9 ES5中的数组方法》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 办理西蒙弗雷泽大学(本科)学历认证『微信171922772』SFU学位证成绩单使馆认证Simon Fraser University

    办理西蒙弗雷泽大学(本科)学历认证『微信171922772』SFU学位证成绩单使馆认证Simon Fraser University Q.微信:171922772办理教育部国外学历学位认证海外大学毕业 ...

  2. Python random模块(获取随机数)常用方法和使用例子

    random.randomrandom.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0 random.uniformrandom.uniform(a, b),用 ...

  3. 20170114 - Mac 向上一级文件夹快捷键

    以前使用XtraFinder来实现向上跳转文件夹,Mac其实自带的向上一级文件夹,只是没有那么明显, Mac下跳转上一级文件夹的快捷键是 Command + Up Arrow,即: ⌘ ↑

  4. Ubuntu 16 04 安装KVM

    apt-get install qemu-kvm ubuntu-vm-builder bridge-utils http://www.linuxidc.com/Linux/2016-06/132188 ...

  5. HTML5学习总结——HTML5入门与新增标签

    一.HTML5概要 1.1.为什么需要HTML5 概念: HTML5 是继 HTML4.01, XHTML 1.0 和 DOM 2 HTML 后的又一个重要版本, 旨在消除富 Internet 程序( ...

  6. 进度管理工具 planner

    ganttproject 太简单,连个子项目都做不了.(也可能是我不会用,后来发现用缩进就可以了.呵呵).又重新有网上搜了一下,发现PLANNER符合我的想法... *进官网,下载. #tar xvJ ...

  7. 前端知识点-JS相关知识点

    1.谈谈你对Ajax的理解?(概念.特点.作用) AJAX全称为"Asynchronous JavaScript And XML"(异步JavaScript和XML) 是指一种创建 ...

  8. Laravel默认使用utf8_unicode_ci 即使数据库是utf8_general_ci

    这样做的后果是,不方便和utf8_general_ci字符串字段进行JOIN查询ON.

  9. 专注VR/AR广告 ,内容感知广告公司Uru获80万美元投资

    随着AR/VR技术不断地跃进,越来越多的公司开始运用这项技术为消费者提供广告和营销信息.Uru是一家打造计算机视觉驱动内容广告的公司,专注于数字视频和VR/AR类似的沉浸式媒介,就在刚刚这家公司宣布完 ...

  10. mysql批量插入之提高插入效率

    INSERT INTO insert_table (datetime, uid, content, type) VALUES ('0', 'userid_0', 'content_0', 0); IN ...