《JS权威指南学习总结--7.9 ES5中的数组方法》
内容要点:
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中的数组方法》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- C#Redis字符串
上周六通宵打牌周日白天只睡3小时累成狗,从今天起以后不能玩太大的了,小赌怡情大赌伤身,和同事朋友有空玩玩还是好的.今天公司外面马路上有人挂灯笼时死了一个人,哎,快过年了悲剧又发生了,真是生命是脆弱的. ...
- 【顶】在node环境下玩转less
1.先搭建node.js环境 具体步骤请点我 2.运行node.js环境 唤出dos窗口→进入工程目录→输入 →成功运行 3.关于less
- C# Volatile 类
关于C#中Volatile类的具体信息,请访问MSDN: https://msdn.microsoft.com/en-us/library/system.threading.volatile(v=vs ...
- Logstash使用grok过滤nginx日志(二)
在生产环境中,nginx日志格式往往使用的是自定义的格式,我们需要把logstash中的message结构化后再存储,方便kibana的搜索和统计,因此需要对message进行解析. 本文采用grok ...
- 前端技术——WebFont与Sprite
一.WebFont web font是应用在web中的一种字体技术,在CSS中使用font-face定义新的字体. 我们在文档中显示的字体应该在系统中能找到才会正常显示,比如你在word中使用了黑体字 ...
- CODE[VS]-保留两位小数-浮点数处理-天梯青铜
题目描述 Description 保留两位小数输出一个浮点数. 输入描述 Input Description 一个浮点数.double范围内 输出描述 Output Description 保留两位小 ...
- ubuntu_虚拟机和SD卡链接失败,可能的原因
这个问题很简单吧,但是自己解决却用了很长时间,说一下方法吧! 1.有的虚拟机不兼容USB3.0的接口,所以在接SD卡(读卡器)时,请将读卡器拔出,插入笔记本USB2.0的接口上(当时自己没注意到这点, ...
- Oracle 收集统计数据
查看最新用户表统计信息 select owner,table_name,last_analyzed from dba_tables where owner not like '%SYS%' order ...
- 相机标定 matlab opencv ROS三种方法标定步骤(3)
三 , ROS 环境下 如何进行相机标定 刚开始做到的时候遇到一些问题没有记录下来,现在回头写的时候都是没有错误的结果了,首先使用ROS标定相机, 要知道如何查看节点之间的流程图 rosrun r ...
- tablesorter周边文档
一.简介: Tablesorter作用于一个标准的HTML表格(有THEAD,TBODY),实现静态排序:主要特点包括: (1) 多列排序: (2) 支持文本.URI地址.数值.货币.浮点数.IP地 ...