内容要点:

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. Nexpose

    下载: https://www.rapid7.com/products/nexpose/nexpose-enterprise-trial-thank-you.jsp注册: https://www.ra ...

  2. iOS strong与weak的使用

    strong修饰的属性是强指针类型的,weak修饰的属性是弱指针类型的 ARC对于内存中的对象管理机制,当某个对象没有被强指针指向的时候,该对象就会被销毁. 所以不适当的使用strong和weak修饰 ...

  3. 国内首家MR头显公司于CES惊艳亮相

    在刚刚过去的CES2017大会上,我们看到了许多较为优秀的VR产品,而在这里面,有一家名不见经传的中国公司易瞳发布了一款兼具VR和AR功能的头显VMG-MARK.它的外观与联想VR和骁龙VR820等产 ...

  4. 问题记录2:TypeError: write() argument must be str, not bytes

    今天试了下用requests模块的get()方法来下载图片,写入文件的时候不能写入二进制,然后将打开方式改成二进制的就好了. 原因是,f.content的存储方式是二进制,而文件正常打开默认是字符串的 ...

  5. 简易富文本编辑器bootstrap-wysiwyg源码注释

    好久没写随笔了,因为最近比较忙,小公司基本都是一个前端干所有属于和部分不属于前端的事情,所以就没空弄了,即使想分享,也因为没有时间和精力就搁置了. 这周周六日休息,正好时间比较充裕(ps:目前处在单休 ...

  6. [读书笔记]telnet与http服务器一次直接对话

    1.打开电脑telnet客户端应用 控制面板 >程序和功能 > 打开或者关闭windows功能 > telnet客户端 勾选,并确认. 2.执行telnet命令 a:cmd进入控制台 ...

  7. OllyDBG V1.10聆风听雨汉化版

    软件名称:OllyDBG V1.10聆风听雨汉化版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 3.84MB 图片预览: 软件简介: Ollydbg2. ...

  8. pyhon的数据类型

    1.数字 整型和浮点型 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2147483648-2147483647在64位系统上,整数的位数为64位,取值范围为-2** ...

  9. QLibraryInfo

        读取 qt.conf 文件, 获取 Qt Library 的信息.     通常会在以下三个路径查找conf文件:         :/qt/etc/qt.conf(使用资源系统时)      ...

  10. [DP优化方法之虚树]

    首先我们看一篇文章 转自xyz: 给出一棵树. 每次询问选择一些点,求一些东西.这些东西的特点是,许多未选择的点可以通过某种方式剔除而不影响最终结果. 于是就有了建虚树这个技巧..... 我们可以用l ...