数组(Array)是有序数据集合,具有复合型结构,属于引用型数据。数组的结构具有弹性,能够自动伸缩。数组长度可读可写,能够动态控制数组的结构。数组中每个值称为元素,通过下标可以索引元素的值,对元素的类型没有限制。在JavaScript中数组主要用于数据处理和管理。
1、定义数组
1.1、构造数组
使用new运算符调用Array()类型函数,可以构造新数组。
【示例1】直接调用Array()函数,不传递参数,可以创建一个空数组:
var a = new Array(); //空数组
【示例2】传递多个值,可以创建一个实数组:
var a = new Array(1,true,"string",[1,2],{x:1,y:2}); //实数组
每个参数指定一个元素的值,对值的类型没有限制。参数的顺序是数组元素的顺序,数组的length属性值等于所传递参数的个数。
【示例3】传递一个数值参数,可以定义数组的长度,即包含元素的个数:
var a = new Array(5); //指定长度的数组
参数值等于数组的length属性值,每个元素的默认值为undefined。
1.2、数组直接量
使用数组直接量定义数组是最简便、最高效的方法。数组直接量的语法格式如下:
[元素1,元素2,…,元素n]
在中括号中包含多个值列表,值之间以逗号分隔。
【示例】使用数组直接量定义数组:
var a = []; //空数组
var a = [1,true,"0",[1,0],{x:1,y:0}]; //包含具体元素的数组
ECMAScript 6新增Set类型的数据结构,本质与数组类似。不同在于,Set中只能保存不同元素,如果元素相同则会被忽略。例如:
let set = new Set([2,3,4,5,5]); //返回[2,3,4,5]
1.3、空位数组
空位数组就是数组中包含空元素。所谓空元素,就是在语法上数组中两个逗号之间没有任何值。出现空位数组的情况如下:
直接量定义:
var a = [1, , 2];
a.length; //返回3
注意:如果最后一个元素后面加逗号,不会产生空位,与没有逗号时效果一样:
var a = [1, 2, ];
a.length; //返回2
构造函数定义:
var a = new Array(3); //指定长度的数组
a.length; //返回3,产生3个空元素
delete删除:
var a = [1, 2, 3];
delete a[1];
console.log( a[1] ); //undefined
console.log( a.length ); //3
上面代码使用delete命令删除数组的第2个元素,这个位置就形成了空位。
空元素可以读写,length属性不排斥空位。如果使用for语句和length属性遍历数组,空元素都可以被读取,空元素返回值为undefined:
var a = [, , ,];
for(var i =0; i<a.length;i++)
console.log( a[i]); //返回3个undefined
注意:空元素与元素的值为undefined是两个不同的概念,虽然空元素的返回值也是undefined。JavaScript在初始化数组时,只有真正存储有值的元素才可以分配内存。
使用forEach()方法、for/in语句以及Object.keys()方法进行遍历时,空元素都会被跳过,但是值为undefined元素能够正常被迭代:
var a = [, , undefined,];
for (var i in a) {
console.log(i); //返回2,仅读取第3个元素
}
console.log(a.length); //返回3,包含3个元素
1.4、关联数组
关联数组是一种数据格式,也称为哈希表。使用关联数组检索数据,速度优于数组。两者区别如下:
- 数组:以正整数为下标,数据排列有规律,类型为Array。
- 关联数组:以字符串为下标,数据排列没有规律,类型为Object。
【示例】数组下标false、true将不会被强制转换为数字0、1,JavaScript会把变量a视为对象,false和true转换为字符串被视为对象的属性名:
var a = []; //声明数组
a[false] = false;
a[true] = true;
console.log( a[0] ); //返回 undefined
console.log( a[1] ); //返回 undefined
console.log( a[false] ); //返回 false,
console.log( a[true] ); //返回 true
console.log( a["false"] ); //返回 false,
console.log( a["true"] ); //返回 true
1.5、类数组
类数组也称为伪类数组,即类似数组结构的对象。该对象的属性名类似数组下标,为非负整数,从0开始,有序递增,同时包含length属性,以方便对类数组执行迭代操作。
【示例1】obj是一个对象,不是一个数组,当使用下标为其赋值时,实际上是定义属性:
var obj = {}; //定义对象直接量
obj[0] = 0; //属性0
obj[1] = 1; //属性1
obj[2] = 2; //属性2
obj.length = 3; //属性length
由于数字是非法的标识符,所以不能使用点语法访问,但是可以使用中括号语法访问:
console.log( obj["2"] );
提示:ECMAScript 6新增Array.from()方法,该方法能够把一个类数组对象或者可遍历对象转换成一个真正的数组。例如:
let arrayLike = {0: 'tom', 1: '65', 2: '男','length': 3} //定义类数组
let arr = Array.from(arrayLike) //转换为数组
console.log(arr) //输出 ['tom','65','男']
注意,如果将上面代码中的length属性去掉,则将返回一个长度为0的空数组;如果对象的属性名不是数字类型,或者字符串型的数字,则返回指定长度的数组,数组元素均为undefined。
【示例2】将Set结构的数据转换为真正的数组:
let arr = [1,2,3,3] //定义数组
let set = new Set(arr) //转换为Set
console.log(Array.from(set)) //转换为数组之后,再输出[1, 2, 3]
Array.from()还可以接收第二个参数,作用类似于数组的map()方法,用来对每个元素进行处理,将处理后的值放入返回的数组:
let arr = [1,2,3,3] //定义数组
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) //输出 [ 2, 3, 4 ]
【示例3】将字符串转换为数组:
let str = 'hello world!';
console.log(Array.from(str)) //["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
注意:如果Array.from()的参数是一个真正的数组,则直接返回一个一模一样的新数组。
2、访问数组
2.1、读写数组
使用中括号([])可以访问数组。中括号左侧是数组名称,中括号内为数组下标:
数组[下标表达式]
下标表达式是值为非负整数的表达式。一般下标从0开始,有序递增,通过下标可以索引对应位置元素的值。
【示例1】使用中括号为数组写入数据,然后再读取数组元素的值:
var a = []; //声明一个空数组
a[0] = 0; //为第1个元素赋值为0
a[2] = 2; //为第3个元素赋值为2
console.log( a[0] ); //读取第1个元素,返回值为0
console.log( a[1] ); //读取第2个元素,返回值为undefined
console.log( a[2] ); //读取第3个元素,返回值为2
【示例2】使用for语句批量为数组赋值,其中数组下标是一个递增表达式:
var a = new Array(); //创建一个空数组
for( var i = 0; i < 10; i ++ ){ //循环为数组赋值
a[i ++ ] = ++ i; //不按顺序为数组元素赋值
}
console.log( a ); //返回2,,,5 ,,,8,,, 11
【示例3】ECMAScript 6开始支持解构表达式,包括数组结构和对象结构。例如,分别解构数组中每个元素的值,以及对象中每个键的值:
let arr = [1,2,3] ; //定义数组
const [x,y,z] = arr; // x、y、z将与arr中的每个对应位置进行取值
let person = {name:"jack", age:21} //定义对象
const {name,age } = person; //解构对象获取每个键的值
提示:ECMAScript 6新增展开运算符,用三个连续的点(…)表示,它能够将字面量对象展开为多个元素,相当于把对象打散为一个个元素。例如:
const arr = ["a", "b", "c"];
console.log(...arr); //展开为 a b c
2.2、访问多维数组
使用多个叠加的中括号语法可以访问多维数组,具体说明如下:
二维数组: 数组[下标表达式] [下标表达式]
三维数组: 数组[下标表达式] [下标表达式] [下标表达式]
以此类推。
【示例】设计一个二维数组,然后分别访问第一行第一列的元素值,以及第二行第二列的元素值:
var a = []; //声明二维数组
a[0] = [1,2]; //为第1个元素赋值为数组
a[1] = [3,4]; //为第2个元素赋值为数组
console.log(a[0][0]) //返回1,读取第1个元素的值
console.log(a[1][1]) //返回4,读取第4个元素的值
注意:在存取多维数组时,左侧中括号内的下标值不能够超出数组范围,否则就会抛出异常。如果第一个下标超出数组范围,返回值为undefined,表达式undefined[1]显然是错误的。
2.3、数组长度
使用数组对象的length属性可以获取数组的长度,JavaScript允许length的最大值等于2^32-1
。
【示例1】定义一个空数组,然后为下标等于100的元素赋值,则length属性返回101。因此,length属性不能体现数组元素的实际个数:
var a = []; //声明空数组
a[100] =2;
console.log(a.length); //返回101
length属性可读可写,是一个动态属性。length属性值也会随数组元素的变化而自动更新。同时,如果重置length属性值,也将影响数组的元素,具体说明如下:
- 如果length属性被设置了一个比当前length值小的值,则数组会被截断,新长度之外的元素值都会丢失。
- 如果length属性被设置了一个比当前length值大的值,那么空元素就会被添加到数组末尾,使得数组增长到新指定的长度,读取值都为undefined。
【示例2】演示length属性值的动态变化,以及对数组的影响:
var a = [1,2,3]; //声明数组直接量
a.length = 5; //增长数组长度
console.log(a[4]); //返回undefined,说明该元素还没有被赋值
a.length = 2; //缩短数组长度
console.log(a[2]); //返回undefined,说明该元素的值已经丢失
2.4、使用for迭代数组
for和for/in语句都可以迭代数组。for语句需要配合length属性和数组下标实现,执行效率没有for/in语句高。另外,for/in语句会跳过空元素。
【示例1】使用for语句迭代数组,过滤所有数字元素:
var a = [1, 2, ,,,,,,true,,,,,,, "a",,,,,,,,,,,,,,,4,,,,,56,,,,,,"b"]; //定义数组
var b = [], num=0;
for( var i = 0; i < a.length ; i ++ ){ //遍历数组
if( typeof a[i] == "number" ) //如果为数字,则返回该元素的值
b.push( a[i]);
num++; //计数器
}
console.log( num ); //返回42,说明循环了42次
console.log( b ); //返回[1,2,4,56]
【示例2】使用for/in语句迭代示例1中的数组a。在for…in循环结构中,变量i表示数组的下标,而a[i]为可以读取指定下标的元素值:
var b = [], num=0;
for( var i in a ){ //遍历数组
if( typeof a[i] == "number" ) //如果为数字,则返回该元素的值
b.push( a[i]);
num++; //计数器
}
console.log( num ); //返回7,说明循环了7次
console.log( b ); //返回[1,2,4,56]
通过计时器可以看到,for/in迭代数组,仅循环了7次,而for语句循环了42次。
2.5、使用forEach迭代数组
使用forEach方法可以为数组执行迭代操作,具体语法格式如下:
array.forEach(callbackfn[, thisArg])
参数说明:
- callbackfn:回调函数,该函数包含元素值、元素下标索引和数组对象3个参数。
- thisArg:可选参数,设置回调函数中this引用的对象。如果省略,则this值为undefined。
forEach方法将会为数组中每个元素调用回调函数一次,但是不会为空位元素调用该回调函数。map方法返回一个新数组,新数组包含回调函数返回值的列表。
提示:filter方法不仅可以被数组对象调用,也允许伪类数组使用,如arguments参数对象等。
【示例1】使用forEach迭代数组a,然后计算数组元素的和并输出:
var a = [10, 11, 12], sum = 0;
a.forEach(function(value){
sum += value;
});
console.log(sum); //返回33
【示例2】使用foeEach迭代数组,在迭代过程中,先读取元素的值,乘方之后,再回写该值,实现对数组的修改:
var obj = {
f1: function(value, index, array) {
console.log( "a[" + index + "] = " + value );
array[index] = this.f2(value);
},
f2: function(x) { return x * x }
};
var a = [12, 26, 36];
a.forEach(obj.f1, obj);
console.log(a); //返回[144,676,1296]
3、操作数组
3.1、栈读写
使用push()和pop()方法可以在数组尾部执行操作。其中,push()方法能够把一个或多个参数值附加到数组的尾部,并返回添加元素后的数组长度。pop()方法能够删除数组中最后一个元素,并返回被删除的元素。
【示例】使用push()和pop()方法在数组尾部执行交替操作,模拟栈操作。栈操作的规律是:先进后出,后进先出:
var a = []; //定义数组,模拟空栈
console.log( a.push(1) ); //进栈,栈值为[1],length为1
console.log( a.push(2) ); //进栈,栈值为[1,2],length为2
console.log( a.pop() ); //出栈,栈值为[1],length为1
console.log( a.push(3,4) ); //进栈,栈值为[1,3,4],length为3
console.log( a.pop() ); //出栈,栈值为[1, 3],length为2
console.log( a.pop() ); //出栈,栈值为[1],length为1
3.2、队列读写
使用unshift()和shift()方法可以在数组头部执行操作。其中,unshift()能够把一个或多个参数值附加到数组的头部,并返回添加元素后的数组长度。
shift()方法能够删除数组的第一个元素,并返回该元素,然后将余下所有元素前移一位,以填补数组头部的空缺。如果数组为空,shift()将不进行任何操作,返回undefined。
【示例】将pop()与unshift()方法结合,或者将push()与shift()方法结合,可以模拟队列操作。队列操作的规律是:先进先出,后进后出。下面利用队列把数组元素的所有值放大10倍:
var a = [1,2,3,4,5]; //定义数组
for(var i in a){ //遍历数组
var t = a.pop(); //尾部弹出
a.unshift(t*10); //头部推入,把推进的值放大10倍
}
console.log(a); //返回[10,20,30,40,50]
3.3、删除元素
使用pop()方法可以删除尾部的元素,使用shift()方法可以删除头部的元素。也可以使用下面3种方法删除元素。
【示例1】使用delete运算符删除指定下标位置的元素,删除后的元素为空位元素,删除数组的length保持不变:
var a = [1, 2, true, "a", "b"]; //定义数组
delete a[0]; //删除指定下标的元素
console.log( a); //返回[, 2, true, "a", "b"]
【示例2】使用length属性可以删除尾部的一个或多个元素,甚至可以清空整个数组。删除元素之后,数组的length将会动态地保持更新:
var a = [1, 2, true, "a", "b"]; //定义数组
a.length = 3 ; //删除尾部2个元素
console.log( a); //返回[1, 2, true]
【示例3】使用splice()方法可以删除指定下标位置后一个或多个数组元素。该方法的参数比较多,功能也很多,本节示例仅演示删除数组元素。其中,第一个参数为操作的起始下标位置,第二个参数指定要删除元素的个数:
var a = [1,2,3,4,5]; //定义数组
a.splice(1,2) //执行删除操作
console.log(a); //返回[1, 4, 5]
在splice(1,2,3,4,5)方法中,第一个参数值1表示从数组a的第二个元素位置开始,删除两个元素,删除后数组a仅剩下3个元素。
3.4、添加元素
使用push()方法可以在尾部添加一个或多个元素,使用unshift()方法可以在头部附加一个或多个元素。也可以使用下面3种方法添加元素。
【示例1】通过中括号和下标值,可以为数组指定下标位置添加新元素:
var a = [1,2,3]; //定义数组
a[3] =4 ; //为数组添加1个元素
console.log(a); //返回[1,2,3,4]
【示例2】concat()方法能够把传递的所有参数按顺序添加到数组的尾部。下面代码为数组a添加3个元素:
var a = [1,2,3,4,5]; //定义数组
var b = a.concat(6,7,8); //为数组a连接3个元素
console.log(b); //返回[1,2,3,4,5,6,7,8]
【示例3】使用splice()方法在指定下标位置后添加一个或多个元素。splice()方法不仅可以删除元素,也可以在数组中插入元素。其中,第一个参数为操作的起始下标位置,设置第二个参数为0,不执行删除操作,然后通过第三个及后面参数设置要插入的元素:
var a = [1,2,3,4,5]; //定义数组
a.splice(1,0,3,4,5) //执行插入操作
console.log(a); //返回[1,3,4,5,2,3,4,5]
在上面代码中,第一个参数值1表示从数组a的第一个元素位置后,插入元素3、4和5。
3.5、截取数组
1.splice()
splice()方法可以添加、删除元素,具体语法格式如下:
array.splice(index,howmany,item1,...,itemX)
参数说明:
- index:设置操作的下标位置。
- howmany:可选参数,设置要删除多少元素及数字类型。如果为0,则表示不删除元素;如果未设置该参数,则表示删除从index开始,到原数组结尾的所有元素。
- item1, …, itemX:设置要添加到数组的新元素列表。
返回值是被删除的子数组,如果没有删除元素,则返回的是一个空数组。当index大于length时,被视为在尾部执行操作,如插入元素。
【示例1】在原数组尾部添加多个元素:
var a = [1,2,3,4,5]; //定义数组
var b = a.splice(6,2,2,3); //起始值大于length属性值
console.log(a); //返回[1, 2, 3, 4, 5, 2, 3]
【示例2】如果第1个参数为负值,则按绝对值从数组右侧开始向左侧定位。如果第2个参数为负值,则被视为0:
var a = [1,2,3,4,5]; //定义数组
var b = a.splice(-2,-2,2,3); //第1、第2个参数都为负值
console.log(a); //返回[1, 2, 3, 2, 3, 4, 5]
2.使用slice()方法
slice()方法与splice()方法的功能相近,但是它仅能够截取数组中指定区段的元素,并返回子数组。该方法包含两个参数,分别指定截取子数组的起始和结束位置的下标。
【示例3】从原数组中截取第3~6元素之前的所有元素:
var a = [1,2,3,4,5]; //定义数组
var b = a.slice(2,5); //截取第3~6元素前的所有元素
console.log(b); //返回[3, 4, 5]
3.6、数组排序
1.reverse()
reverse()方法能够颠倒数组内元素的排列顺序,该方法不需要参数。例如:
var a = [1,2,3,4,5]; //定义数组
a.reverse(); //颠倒数组顺序
console.log(a); //返回数组[5,4,3,2,1]
注意:该方法是在原数组上执行操作,而不会创建新的数组。
2.使用sort()方法
sort()方法能够根据指定的条件对数组进行排序。在任何情况下,值为undefined的元素都被排列在末尾。sort()方法也是在原数组上执行操作,不会创建新的数组。
如果没有参数,则按默认的字母顺序对数组进行排序:
var a = ["a","e","d","b","c"]; //定义数组
a.sort(); //按字母顺序对元素进行排序
console.log(a); //返回数组[a,b,c ,d,e]
如果传入一个排序函数,该函数会比较两个值,然后返回一个说明这两个值的相对位置的数字。排序函数应该包含两个参数,假设传入参数为a和b,返回值与a、b的位置关系说明如下:
- 如果a小于b,在排序后的数组中a应该出现在b之前,即位置不变,应返回一个小于0的值;如果a应该出现在b之后,即互换位置,则应返回一个大于0的值。
- 如果a等于b,位置不动,就返回0。
- 如果a大于b,在排序后的数组中a应该出现在b之前,即位置不变,则应返回一个大于0的值;如果a应该出现在b之后,即互换位置,则应返回一个小于0的值。
【示例1】根据排序函数比较数组中每个元素的大小,并按从小到大的顺序执行排序:
function f( a, b ){ //排序函数
return ( a - b ) //返回比较参数
}
var a = [3, 1, 2, 4, 5, 7, 6, 8, 0, 9]; //定义数组
a.sort(f); //根据数字大小由小到大进行排序
console.log( a ); //返回数组[0,1,2 ,3,4, 5,6,7 ,8,9]
如果按从大到小的顺序执行排序,则让返回值取反即可。代码如下所示:
function f( a, b ){ //排序函数
return -( a - b ) //取反并返回比较参数
}
var a = [3, 1, 2, 4, 5, 7, 6, 8, 0, 9]; //定义数组
a.sort(f); //根据数字大小由大到小进行排序
console.log( a ); //返回数组[9,8,7 ,6,5, 4,3,2 ,1,0]
【示例2】把浮点数和整数分开显示:整数排在左侧,浮点数排在右侧:
function f( a, b ){ //排序函数
if( a > Math.floor( a ) ) return 1; //如果a是浮点数,则调换位置
if( b > Math.floor( b ) ) return - 1; //如果b是浮点数,则调换位置
}
var a = [3.55555, 1.23456, 3, 2.11111, 5, 7, 3]; //定义数组
a.sort( f ); //进行筛选
console.log( a ); //返回数组[3,5,7,3,2.11111,1.23456,3.55555]
3.7、数组转换
JavaScript允许数组与字符串之间相互转换。其中,Array对象定义了3种方法,以实现把数组转换为字符串,如下表所示:
【示例1】使用toString()方法输出数组的字符串表示,以逗号进行连接:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; //定义数组
var s = a.toString(); //把数组转换为字符串
console.log( s ); //返回字符串“1, 2, 3, 4, 5, 6, 7, 8, 9, 0”
【示例2】toLocalString()方法与toString()方法的用法基本相同,主要区别在于toLocalString()方法能够使用本地约定分隔符连接生成的字符串:
var a = [1, 2, 3, 4, 5]; //定义数组
var s = a.toLocaleString(); //把数组转换为本地字符串
console.log( s ); //返回字符串“1.00, 2.00 , 3.00 , 4. 00, 5 .00”
在示例2中,toLocalString()方法根据中国大陆的使用习惯,先把数字转换为浮点数之后再执行字符串转换操作。
【示例3】join()方法可以把数组转换为字符串,允许传递一个参数作为分隔符连接每个元素。如果省略参数,默认使用逗号作为分隔符,这时与toString()方法转换操作效果相同:
var a = [1, 2, 3, 4, 5]; //定义数组
var s = a.join("=="); //指定分隔符
console.log( s ); //返回字符串“1==2== 3==4 ==5”
3.8、定位元素
使用indexOf和lastIndexOf方法可以获取指定元素的索引位置。与String的indexOf和lastIndexOf方法的用法相同。
1.indexOf
indexOf返回指定值在数组中第一次匹配项的索引下标,如果没有找到指定值,则返回-1。具体语法格式如下:
array.indexOf(searchElement[, fromIndex])
参数说明:
- searchElement:需要定位的值。
- fromIndex:可选参数,设置开始搜索的索引位置。如果省略,则从开始位置搜索;如果大于或等于数组长度,则返回-1;如果为负数,则从数组长度加上fromIndex的位置开始搜索。
提示:indexOf方法是从左到右进行检索,检索时会使用全等(===)运算符比较元素与searchElement参数值。
【示例1】使用indexOf方法定位“cd”字符串的索引位置:
var a = ["ab", "cd", "ef", "ab", "cd"];
console.log(a.indexOf("cd" )); //1
console.log(a.indexOf("cd", 2)) ; //4
2.lastIndexOf
lastIndexOf返回指定的值在数组中的最后一次匹配项的索引,用法与indexOf相同。
【示例2】使用lastIndexOf方法定位“cd”字符串的索引位置:
var a = ["ab", "cd", "ef", "ab", "cd"];
console.log(a.lastIndexOf("cd") ); //4
console.log(a.lastIndexOf("cd", 2) ); //1
3.9、检测数组
使用Array.isArray方法可以判断一个对象是否为数组。使用运算符in可以检测一个值是否在数组中。
【示例】使用typeof运算符无法检测数组类型,而使用Array.isArray方法比较方便、准确:
var a = [1, 2, 3]; //定义数组直接量
console.log( typeof a ); //返回“object”
console.log( Array.isArray(a) ) ; //返回true
3.10、检测元素
1.检测是否全部符合指定条件
使用every方法可以检测数组的所有元素是否全部符合指定的条件,具体语法格式如下:
array.every(callbackfn[, thisArg])
参数说明:
- callbackfn:回调函数,该函数可以包含3个参数:元素值、元素下标索引和数组对象。
- thisArg:可选参数,设置回调函数中this引用的对象。如果省略,则this值为undefined。
every方法将会为数组中每个元素调用回调函数一次,但是不会为空位元素调用回调函数。如果每次调用回调函数都返回true,则every返回值为true;否则every返回值为false。如果数组没有元素,则every返回值为true。
提示:filter方法不仅可以被数组对象调用,也允许伪类数组使用。
【示例1】检测数组中的元素是否都为偶数:
function f(value, index, ar) {
if (value % 2 == 0) return true;
else return false;
}
var a = [2, 4, 5, 6, 8];
if (a.every(f)) console.log("都是偶数。");
else console.log("不全为偶数。");
2.检测是否存在符合指定条件的元素
使用some方法可以检测数组是否有符合指定条件的元素,具体语法格式如下:
array.some(callbackfn[, thisArg])
参数说明:
- callbackfn:回调函数,该函数可以包含3个参数:元素值、元素下标索引和数组对象。
- thisArg:可选参数,设置回调函数中this引用的对象。如果省略,则this值为undefined。
some方法将会为数组中每个元素调用回调函数一次,但是不会为空位元素调用回调函数。如果每次调用回调函数都返回false,则some返回值为false;如果全部或者部分调用回调函数返回true,则some返回值为true。如果数组没有元素,则every返回值为false。
提示:filter方法不仅可以被数组对象调用,也允许伪类数组使用。
【示例2】检测数组中的元素的值是否都为奇数。如果some方法检测到偶数,则返回true,并提示不全是偶数;如果没有检测到偶数,则提示全部是奇数:
function f(value, index, ar) {
if (value % 2 == 0) return true;
}
var a = [1, 15, 4, 10, 11, 22];
var evens = a.some(f);
if(evens) console.log("不全是奇数。");
else console.log("全是奇数。");
3.11、映射数组
使用map方法可以为数组执行映射操作,具体语法格式如下:
array.map(callbackfn[, thisArg])
参数说明:
- callbackfn:回调函数,该函数包含元素值、元素下标索引和数组对象3个参数。
- thisArg:可选参数,设置回调函数中this引用的对象。如果省略,则this值为undefined。
map方法将会为数组中每个元素调用回调函数一次,但是不会为空位元素调用回调函数。map方法返回一个新数组,新数组包含回调函数返回值的列表。
【示例】使用map方法映射数组,把数组中每个元素的值除以一个阀值,然后返回余数的新数组,其中回调函数和阀值都以对象的属性进行传递。通过这种方式获取原数组中每个数字的个位数的新数组:
var obj = {
val: 10,
f: function (value) {
return value % this.val;
}
}
var a = [6, 12, 25, 30];
var a1 = a.map(obj.f, obj);
console.log(a1); //6,2,5,0
3.12、过滤数组
使用filter方法可以为数组执行过滤操作,具体语法格式如下:
array.filter(callbackfn[, thisArg])
参数说明:
- callbackfn:回调函数,该函数包含元素值、元素下标索引和数组对象3个参数。
- thisArg:可选参数,设置回调函数中this引用的对象。如果省略,则this值为undefined。
filter方法将会为数组中每个元素调用回调函数一次,但是不会为空位元素调用回调函数。filter返回一个新数组,新数组包含回调函数返回true的所有元素。
提示:filter方法不仅可以被数组对象调用,也允许伪类数组使用。
提示:filter方法不仅可以被数组对象调用,也允许伪类数组使用:
var f = function(value) { //过滤函数
if (typeof value !== 'number') return false; //如果元素值不是数字,则直接过滤
else return value >= this.min && value <= this.max ; //如果为10~20,则保留
}
var a = [6, 12, "15", 16, "the", -12]; //待处理的数组
var obj = { min: 10, max: 20 } //设置范围对象,包含最小值和最大值属性
var r = a.filter(f, obj); //执行过滤操作
console.log(r); //返回新数组:12,16
提示:ECMAScript 6新增3个过滤函数,专门用于查找特定元素,简单说明如下:
- find(callback):在每个元素上执行回调函数callback,如果返回true,则返回该元素。
- findIndex(callback):与find类似,不过返回的是匹配元素的下标索引。
- includes(callback):与find类似,如果匹配到元素,则返回true,代表找到了。
3.13、汇总数组
使用reduce和reduceRight方法可以为数组执行汇总操作。
1.reduce
在数组的每个元素上调用回调函数,回调函数的返回值将在下一次被调用时作为参数传入。具体语法格式如下:
array.reduce(callbackfn[, initialValue])
参数说明:
- callbackfn:回调函数。
- initialValue:可选参数,指定初始值。如果指定该参数,则在第一次调用回调函数时,使用该参数值和第一个元素值传入回调函数;如果没有指定该参数,则使用第一个元素值和第二个元素值传入回调函数。然后,依次在下一个元素上调用函数,并把上一次回调函数的返回值与当前元素的值传入回调函数。
reduce返回值是最后一次调用回调函数的返回值。reduce不会为空位元素调用该回调函数。
回调函数的语法格式如下:
function callbackfn(previousValue, currentValue, currentIndex, array)
回调函数的参数说明如下:
- previousValue:上一次调用回调函数的返回值。如果reduce包含参数initialValue,则在第一次调用函数时,previousValue为initialValue。
- currentValue:当前元素的值。
- currentIndex:当前元素的下标索引。
- array:数组对象。
【示例1】使用reduce方法汇总数组内元素的和:
function f(pre, curr) {
return pre +curr;
}
var a = [1, 2, 3, 4];
var r = a.reduce(f);
console.log(r); //返回10
2.reduceRight
reduceRight与reduce方法的语法和用法基本相同,唯一的区别是:reduceRight从右向左对数组中的所有元素调用指定的回调函数。
示例2】使用reduceRight方法,以" "为分隔符,按从右到左的顺序把数组元素的值连接在一起,返回字符串“4 3 2 1”。如果调用reduce方法,则返回字符串为“1 2 3 4”:
function f (pre, curr) {
return pre + " " + curr;
}
var a = [1, 2, 3, 4];
var r = a.reduceRight(f);
console.log(r); //返回“4 3 2 1”