前言
除 Object 之外, Array 类型恐怕是 ECMAScript 中最常用的类型了. 而且, ECMAScript中的数组与其它多语言中的数组有着相当打的区别. 虽然 ECMAScript 数组与其它语言中的数组都是数据的有序列表, 但与其他语言不同的是, ECMAScript 数组的每一项可以保存任何类型的数据. 也就是说, 可以用数组的第一个位置来保存字符串, 用第二个位置来保存数值, 用第三个位置来保存对象, 以此类推. 而且, ECMAScript 数组的大小是可以动态调整的, 即可以随着数据的添加自动增长以容纳新增数据.
创建数组的不同方式
第一种使用 Array 的构造函数:
1 2 3 4 5 6 7 8 9
| var colors = new Array(); var colors = new Array(20); var colors = new Array('white'); var colors = Array(3); var colors = Array('white');
|
第二种是使用数组字面量表示法:
1 2 3
| var colors = ['white', 'black', 'purple']; var colors = [];
|
注意:
请不要在最后一个元素后面加 , 用以隔开前后元素, 如下案例:
1 2 3
| var colors = ['white', 'black', 'purple',]; var colors = [, , ,];
|
获取数组的长度
1 2
| var colors = ['white', 'black', 'purple']; var len = colors.length;
|
检测是数组. 常常被问到的一个面试题
1 2 3 4 5 6 7 8
| function isArrayFn(val) { if (typeof Array.isArray === 'function') { return Array.isArray(val); } else { return Object.prototype.toString.call(val) === '[object Array]'; } }
|
以上代码为最优解决方法 ~
扩展1:
typeof 可判断 - Function, String, Number, Boolean, Undefined
扩展2:
也可用 arr instanceof Array 判断是否是数组
扩展3:
也可用 arr.constructor === Array 判断是否是数组
数组之 - 转化方法
简单的转换方式:
1 2 3 4 5
| var colors = ['white', 'black', 'purple']; console.log(colors.toString()); console.log(colors.toLocaleString()); console.log(colors.valueOf()); console.log(colors);
|
不同分隔符转换方式, 符号可自定义:
1 2 3
| var colors = ['white', 'black', 'purple']; console.log(colors.join(',')); console.log(colors.join('||'));
|
数组之 - 栈方法
栈的特点是 LIFO
(Last-In-First-Out) 后进先出的数据结构, 也就是后添加的项最早被移除.
模拟栈的方式, 插入(即推入), 移除(即弹出), 只发生在一个位置 —— 栈的顶部.
ECMAScript 为数组模拟栈的方式提供了 push()
和 pop()
.
1 2 3 4 5 6
| var colors = ['white', 'black']; colors.push('purple'); console.log(colors); var item = colors.pop(); console.log(item);
|
数组之 - 队列方法
队列的特点是 FIFO
(First-In-First-Out) 先进先出的数据结构, 即在队列的列表末尾添加项, 从列表的前端移除项.
模拟队列的方式, ECMAScript 为数组移除列表前端提供了 shift()
的方法.
1 2 3 4 5 6
| var colors = ['white', 'black']; colors.push('purple'); console.log(colors); var item = colors.shift(); console.log(item);
|
另外, ECMAScript 还为数组提供了与 shift()
相反的 unshift()
, unshift()
能在数组前端添加任意项并返回新数组的长度. 因此, 同时使用 unshift()
和 pop()
可以从相反的方向来模拟队列, 即在数组的前端添加项, 从数组的末端移除项, 如下:
1 2 3 4 5 6
| var colors = ['white', 'black']; colors.unshift('blue'); console.log(colors); var item = colors.pop(); console.log(item);
|
数组之 - 重排序方法
数组已经存在两个可以直接用来重排序的方法, 即 reverse()
和 sort()
1 2 3 4
| var num = [6, 3, 7, 2, 9]; console.log(num.reverse()); console.log(num.sort());
|
reverse()
反转数组. sort()
对数组升序排序. 但是以上两个都不够灵活, 如下案例:
1 2
| var num = [6, 5, 15, 2, 9]; console.log(num.sort());
|
经 sort()
重排序后, 15 换在 其他各位数的前面, 因为 sort()
会把各项先转换成 toString()
然后在进行比较, 显然 "15"
的字符串位于其他个位的字符串, 所以直接用 sort()
比较是有缺陷的, 但是好的一点是, sort()
可以接收一个比较函数最为参数, 所以我们可以对 sort()
进行扩展, 如下代码:
1 2 3 4 5 6 7 8 9
| function compare(value1, value2) { if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } }
|
compare()
函数接收两个参数, 如果第一个参数应该位于第二个参数之前则返回 -1
, 如果两个参数相等, 则返回 0
, 如果第一个参数应该位于第二个参数之后则返回 1
. 使用此方法比较如下:
1 2 3
| var num = [6, 5, 15, 2, 9]; num.sort(compare); console.log(num.sort());
|
这个比较函数适用于大多数的数据类型, 只要将其函数做为参数传递给 sort()
即可.
另外, 上述 compare()
的扩展是升序排序, 当然也可以进行降序排序. 如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function compare(value1, value2) { if (value1 < value2) { return 1; } else if (value1 > value2) { return -1; } else { return 0; } } var num = [6, 5, 15, 2, 9]; num.sort(compare); console.log(num.sort());
|
数组之 - 操作方法
ECMAScript 为操作已经包含在数组中项提供了很多方法.
concat()
方法可以基于当前数组创建一个新数组, 不会影响原数组. 直接看代码:
1 2 3 4 5 6
| var colors = ['white', 'black', 'purple']; var colors2 = colors.concat(); console.log(color2); var colors3 = colors.concat('yellow', ['blue', 'orange']); console.log(color3);
|
slice()
方法能够基于当前数组中的一个或多个项创建一个新数组, 不会影响原数组. 直接看代码:
1 2 3 4 5 6
| var colors = ['white', 'black', 'purple', 'blue', 'green']; var colors2 = colors.slice(1); console.log(colors2); var colors3 = colors.slice(1, 3); console.log(colors3);
|
splice()
方法可谓是最强大的, 它是向数组的中部插入项, 也可删除项的同时插入长度不等的集合, 主要用途有: 删除, 插入, 替换. 注意的是, 该方法会影响原数组.
1 2 3 4 5 6 7 8 9 10 11 12
| var colors = ['white', 'black', 'purple']; var removed = colors.splice(0, 1); console.log(colors); console.log(removed); removed = colors.splice(1, 0, 'yellow', 'orange'); console.log(colors); console.log(removed); removed = colors.splice(1, 1, 'red', 'green'); console.log(colors); console.log(removed);
|
数组之 - 位置方法
ECMAScript5 为数组实例添加了两个位置方法: indexOf()
和 `lastIndexOf(), 可用于查找特定项在数组中的位置, 该两个方法都有两个参数, 第一个参数为要查找的项, 第二个参数为可选参数, 表示查找起点位置的索引.
1 2 3 4 5 6 7 8 9 10 11
| var num = [6, 5, 15, 2, 9]; console.log(num.indexOf(5)); console.log(num.indexOf(20)); console.log(num.indexOf(2)); console.log(num.lastIndexOf(15)); console.log(num.indexOf(3, 3)); console.log(num.indexOf(9, 3)); console.log(num.lastIndexOf(5, 3));
|
1 2 3 4 5 6
| var person = {name: 'awesome'}; var people = [{name: 'awesome'}]; var morePeople = [person]; console.log(people.indexOf(person)); console.log(morePeople.indexOf(person));
|
支持以上两个方法的浏览器包括 IE 9+, Firefox 2+, Safari 3+, Opera 9.5+, Chrome
数组之 - 迭代方法
ECMAScript5 为数组定义了 5 个迭代方法, 每个方法都接收两个参数, 第一个参数为要在每一项上运行的函数, 第二个参数为可选项表示运行该函数的作用域对象 —— 影响 this 的值. 传入这些方法中的函数会接收三个参数, 分别是: 数组项的值, 该项在数组中的位置和数组对象本身. 但是他们相对应的返回值不同, 首先下面是这 5 个迭代方法:
- every() - 如果该函数对每一项都返回 true, 则返回 true
- filter() - 返回该函数会返回 true 的项组成的数组
- forEach() - 没有返回值, 相当于循环
- map() - 返回每次函数调用的结果组成的数组
- some() - 如果该函数对任一项返回 true, 则返回 true
以上方法都不会修改数组中的包含的值, 请看代码演示:
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var everyRes = num.every(function(item, index, array) { return (item > 2); }) console.log(everyRes);
|
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var someRes = num.some(function(item, index, array) { return (item > 2); }) console.log(someRes);
|
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var filterRes = num.filter(function(item, index, array) { return (item > 2); }) console.log(filterRes);
|
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var mapRes = num.map(function(item, index, array) { return (item * 2); }) console.log(mapRes);
|
1 2 3 4 5 6
| var num = [6, 5, 15, 2, 9]; num.forEach(function(item, index, array) { console.log(item); })
|
支持这些迭代方法的浏览器包括 IE 9+, Firefox 2+, Safari 3+, Opera 9.5+, Chrome
数组之 - 归并方法
ECMAScript5 还新增了两个归并数组的方法, reduce()
和 reduceRight()
. 这两个方法都会迭代数组的所有项, 然后构建一个最终返回值.
reduce()
从数组的第一项开始(即 0 项), 逐个向后遍历
reduceRight()
从数组的最后一项开始(即 length - 1 项), 逐个向前遍历
以上两个方法, 接收两个参数, 第一个参数是每项上调用的函数, 第二个参数可选表示做为归并基础的初始值. 该函数方法有 4 个参数, 分别是: 前一个值, 当前值, 项的索引和数组对象本身. 其中特点就是, 当前值会做为下个执行函数的第一个参数, 请看代码:
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var sum = num.reduce(function(prev, cur, index, array) { return prev + cur; }) console.log(sum);
|
1 2 3 4 5 6 7
| var num = [6, 5, 15, 2, 9]; var sum = num.reduceRight(function(prev, cur, index, array) { return prev + cur; }) console.log(sum);
|
两个执行结果是一样的, 但是执行顺序不一样, 因为现在是用于比较基础的逻辑运算.
支持这两个归并函数的的浏览器包括 IE 9+, Firefox 3+, Safari 4+, Opera 10.5+, Chrome
总结
以上出自 << JavaScript 高级程序设计(第3版) >> 对于引用类型 Array 的总结摘录. 供个人温故知新.