无论什么编程语言,数组总是用的最多的引用数据类型之一。JS中的数组有些特殊,它不像Java那种强类型语言那样,一个数组只能存放一种类型的数据。JavaScript允许数组中的每一项的数据类型不同。、
本文分九个层面对JavaScript数组的功能及用法做一个简单的介绍。
创建
数组的创建无非有两种方式:
构造函数:
var arr1 = new Array(1,2,3,4); // [1,2,3,4]
var arr2 = new Array(2); // [,,,]
字面量:
var arr1 = [1,2,3,4];
如上,构造函数Array()在传入一个数值作为参数时,这个数值是数组的长度,显然存在歧义,ES6中的Array.of()方法完善了这一点。
Array.of(1, 2, 3, 4); // [1, 2, 3, 4]
Array.of(2); // [2]
当然,绝大数情况都是使用字面量的形式去创建数组的。
读写
对数组进行读写,最简单的莫过于
var arr = [1, 2, 3, 4];
arr[1]; // 2
arr[1] = 5;
另外,数组的length属性是可写的,改变length值也会改变数组:
arr.length = 5; // [1, 2, 3, 4,]
arr[4]; // undefined
利用length值还可以在数组末尾新增项:
arr[arr.length] = 7; // 数组最后一项的index为 length - 1
复杂一点的读写方式有:push()、pop()、shift()、unshift()
push()、pop()使得数组可以作为栈的一种实现,push()可以接受任意数量的参数,并将其添加至数组尾部返回修改后的数组长度,pop()弹出并返回数组最后一个元素。shift()、push()使数组可以作为队列的一种实现,shift()将数组第一个元素弹出并返回。而unshift()在数组头部添加任意数量的元素并返回长度。
检测
检测一个变量是否为数组类型,最直接的方法:
target instanceof Array
这种方法问题在于如果网页中有多个框架,即存在多个版本的Array构造函数,不同框架的数组实例检测起来就会失败,但这种情况毕竟不常见。
另外就是
Array.isArray(target);
这个API的问题在于过老版本的浏览器不支持ES5,但也不足为道。
检测数组中是否存在某个值,在ES5中往往通过indexOf()实现,但ES6新增了includes()方法,弥补了arr.indexOf(value) === -1;在语义化和忽略了NaN的问题。
var arr = [1, 2, 3, 4, NaN];
arr.includes(NaN); // true
转换
将数组转换为字符串,默认的方法有toString(),toLocalString(),valueOf(),以上三种方法都是对数组的每一项调用该方法,然后用逗号连接这些项;当需要用其他符号连接每一项时,就需要用到join()方法:
var arr = [1, 2, 3, 4, 5];
arr.join('*'); // 1*2*3*4*5
将数组转换为参数列表:使用的是ES6的扩展运算符...,这在函数调用的时候十分有用
function add(x, y, z) {
return x + y + z;
}
add(...[1, 2, 3]); // 6
可以利用这一点对一些只接受参数列表的函数传递数组,从而实现某种需求,如求数组中的最大值:
var arr = [1, 2, 3, 4, 5];
// ES5
Math.max().apply(null, arr);
// ES6
Math.max(...arr);
将其他数据类型(类数组对象、可遍历对象(如arguments对象,NodeList对象))转换为数组:可以用扩展运算符,也可以用Array.from()。
两者的区别在于扩展运算符调用的是目标对象的iterator接口,所以...只能将可遍历对象转换为数组,而Array.from()还可以将类数组对象,即拥有length属性的对象转换为数组。另外Array.from()还可接受第二个参数:作用类似于map函数;第三个参数:第二个参数中的this。
无论是扩展运算符还是Array.from(),在将字符串转换为数组时都会将32位Unicode字符正确识别为一个字符,可以利用这一点来正确读取字符串的长度。
排序
数组实例有两个方法可以对数组排序,分别是reverse() 和 sort()。
reverse()仅仅将数组的顺序反转,而如果简单地调用sort(),无论数组的每一项为何值,都会将其转换为字符串比较,就会出现奇怪的现象:
var arr = [2, 10, 5, 4];
arr.reverse(); // [4, 5, 10, 2]
arr.sort(); // [10, 2, 4, 5]
这是因为字符串比较的是对应位置的Unicode值,因为1在2前面所以10比2小。这样显然是不合理的,需要向sort传入排序规则,如:
var arr = [2, 10, 5, 4];
arr.sort(function(curr, next) {
if (curr < next) {
return -1;
} else if (curr > next) {
return 1;
} else {
return 0;
}
});
arr // [2, 4, 5, 10]
因为arr的每一项都是数值,可以写成
arr.sort(function(curr, next) {
return curr - next;
});
操作
将多个数组或者参数拼入已有的数组————concat(item1, arr, item2...)
concat接收任意多个参数,可以是数组或者其他类型,返回一个新的数组。
// concat不会改变原数组
var arr = [1, 2, 3, 4];
var arr1 = arr.concat(5, [6, 7]);
arr1; // [1, 2, 3, 4, 5, 6, 7]
取出数组中某一段————slice()
slice接收一个或两个参数,接收一个参数时返回这个参数代表的位置到数组末尾的段,接收两个参数时返回两个参数之间的段,"包括头不包括尾。"
// slice也不会改变原数组
var arr = [1, 2, 3, 4];
var arr1 = arr.slice(0, 3);
arr1; // [1, 2, 3]
删除、插入、替换数组中的项————splice(start, delMount, ...replace)
splice的返回值总是删除的项
// splice会改变原数组
var arr = [1, 2, 3, 4];
// 删除
arr.splice(1, 1); // [2]
arr; // [1, 3, 4]
// 插入
arr.splice(1, 0, 2, 5);
arr; // [1, 2, 5, 3, 4]
// 替换
arr.splice(2, 1, 8); // [5]
arr; // [1, 2, 8, 3, 4]
数组内部替换————copyWithin(target, start, end) ES6
此方法返回的是修改后的数组
// copyWithin会改变原数组
var arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3); // [4, 5, 3, 4, 5]
这里省略了end参数,默认为到数组结尾
填充数组————fill(item, start, end)
var arr = [1, 2, 3, 4, 5];
arr.fill(7);
arr; // [7, 7, 7, 7, 7]
arr.fill(8, 0, 2);
arr; // [8, 8, 7, 7, 7]
位置
查找指定元素在数组中的位置————indexOf(item, start)、lastIndexOf(item, start)
// 若数组中无该元素则返回-1, 此处比较机制为全等===
var arr = [1, 2, 3, 4, 5, 2];
arr.indexOf(2); // 1
arr.indexOf(2, 2); // 5
查找符合条件的元素在数组中的位置————findIndex(func(value, index, arr)) ES6
var arr = [1, 2, 3, 4, 5];
arr.findIndex(function(value) {
return value > 3;
}); // 3
迭代
every、filter、forEach、some、map、find(ES6)
迭代方法传入的都是一个函数:
function(value, index, arr) {
if (......) {
// 符合条件
return true
}
}
every: 数组所有项都符合条件时返回true;
some: 数组中任意一项符合条件就返回true;
filter: 返回数组中符合条件的项组成的数组;
forEach: 对数组所有项执行操作,不返回任何值;
map: 对数组每一项执行操作,返回由函数返回值构成的数组;
find: 返回数组中第一个符合条件的项;
Reduce
reduce(function(prev, curr, index, array), initValue),reduce从数组第一项开始执行参数中的函数,其返回值作为第二项的prev,第二个参数可选,指定prev的初始值
var arr = [1, 2, 3, 4];
arr.reduce(function(prev, cur) {
return prev + cur;
}); // 10
reduceRight()是从数组末尾开始执行的,用法与reduce一致。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。