js中数组是一种非常常用数据结构,而且很容易模拟其他的一些数据结构,比如栈和队列。数组的原型Array.prototype
内置了很多方法,下面就来小小总结一下这些方法。
检测数组就不用多说了,使用ECMAScript5新增的Array.isArray()
即可
转换方法
toLocaleString()
toString()
join()
和 valueOf()
所有对象都有
toLocaleString()
toString()
和valueOf()
方法,其中调用数组的toString()
方法会返回数组每个值得字符串形式拼接而成的一个以逗号分隔的字符串。而valueOf()
返回的还是数组。
var arr = [1,2,4];
console.log(arr.toString()) // 1,2,4
console.log(arr.toLocaleString()) // 1,2,4
console.log(arr.valueOf()) // [1,2,4]
join()
可以使用不同分隔符构建字符串,只接受一个参数,即用做分割符的字符串,返回包含数组所以项的字符串
var say = ['h','e','l','l','o'];
say.join('-'); //"h-e-l-l-o"
栈方法
push()
和 pop()
栈是一种后进先出(LIFO)的数据结构,栈中项的插入和移除都发生在一个位置——栈顶。ECMAScript为数组专门提供了
push()
和pop()
方法,实现类似栈的行为。
push()
方法接受任意数量的参数,把他们逐个添加在数组末尾,返回修改后的数组长度。pop()
方法从数组末尾移除最后一项,减少数组length
值,返回移除的项
var stack = [];
console.log(stack.push(3,5,6)) // 3
console.log(stack.push(8)) // 4
console.log(stack.pop()) // 8
队列方法
push()
和 shift()
队列是一种先进先出(FIFO)的数据结构,由于
push()
是向数组末尾添加项,因此要模拟队列只需要一个从数组前端取得项的方法。实现这一操作的数组方法是shift()
,他可以移除数组中的第一项并返回该项。
var queue = [];
console.log(queue.push(3,5,6)) // 3
console.log(queue.push(8)) // 4
console.log(queue.shift()) // 3
*tips: ECMAScript为数组还提供了一个unshift()
方法,其用途与shift()
相反,他能在数组前端添加任意个项并返回新数组的长度。同时使用 unshift()
和 pop()
方法,可以从反方向模拟队列。
重排序方法
reverse()
和 sort()
reverse()
会反转数组的顺序,返回反转后的数组。但是不够灵活,所以有了sort()
方法。默认情况下,sort()
按升序排列数组。最小值在最前面,为了实现排序,sort()
方法会调用每个数组项的toString()
转型方法,然后比较得到的字符串确定如何排序。这种排序方法通常不是最佳方案,因此sort()
方法可以接受一个比较函数,以便我们指定哪个值位于哪个值的前面。比如从小到大排序,可以如下操作:
var nums = [1,3,15,9,6,10,2];
nums.sort(function(before,next){
return before-next;
}); // [1, 2, 3, 6, 9, 10, 15]
操作方法
concat()
slice()
和 splice()
concat()
可以拼接数组,没有参数情况下,复制当前数组返回副本,如果参数是一个或多个数组,该方法会将数组的每一项都添加到结果数组中。如果参数不是数组,这些值会被简单的添加到结果数组的末尾。
slice()
方法可以基于当前数组中的一个或多个项创建新的数组(前闭后开区间),如果不传参数,也会复制当前数组返回副本。concat()
和slice()
均不改变原数组。
splice()
就比较厉害了,是很强大的数组处理方法,可以用来删除、插入、和替换。第一个参数指定开始删除的位置,第二个参数删除的项数,第三个及以后的参数是要插入的项。
var nums = [1,2,4,5,6];
nums.splice(2,0,3);
console.log(nums) // [1, 2, 3, 4, 5, 6]
位置方法
indexOf()
和 lastIndexOf()
这两方法都接收两个参数,要查找的项和开始查找的位置(可选)。
indexOf()
从数组开头位置查找,lastIndexOf()
从数组末尾查找。查找时和数组每一项严格相等比较(===),如果查到,就返回查找项在数组中的位置,查不到就返回-1.
var nums = [1,2,4,5,6];
nums.indexOf(5); // 3
nums.indexOf(9); // -1
迭代方法
every()
filter()
forEach()
map()
some()
ECMAScript5 提供了5个迭代方法,每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域对象——影响
this
的值。传入的函数会接收三个参数:数组项的值,该项在数组的位置,数组对象本身。这5个方法有各自不同的作用:
every()
: 数组每一项运行给定函数,如果该函数每一项都返回true
,则返回true
some()
: 数组每一项运行给定函数,如果该函数任意一项都返回true
,则返回true
filter()
: 数组每一项运行给定函数,返回该函数会返回true
的项组成的数组forEach()
: 数组每一项运行给定函数,该方法无返回值map()
: 数组每一项运行给定函数,返回该函数每次调用的结果组成的数组
以上方法不会改变原数组的值
var arr = [1,2,3,4,5,6,7]
var plus10=arr.map(function(item){
return item+10;
});
console.log(plus10) // [11, 12, 13, 14, 15, 16, 17]
归并方法
reduce()
和 reduceRight()
这两个方法都迭代所有项,然后构建一个最终返回值。
reduce()
从数组开头迭代,reduceRight()
从数组末尾迭代。接收两个参数,在每一项上调用的函数和(可选)作为归并基础的初始值。调用函数接收4个参数:前一个值,当前值,项的索引和数组对象。这个函数返回的任何值都作为第一个参数自动传给下一项。比如累加操作:
var arr = [1,2,3,4,5,6,7,8,9,10]
var sum=arr.reduce(function(pre,cur){
return pre+cur;
});
console.log(sum) // 55
ES6+ 新增方法
entries()
fill()
findIndex()
includes()
entries()
方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
var array = ['a', 'b', 'c'];
var iterator = array.entries();
console.log(iterator.next().value);
// [0, "a"]
console.log(iterator.next().value);
// [1, "b"]
for (let e of iterator) {
console.log(e);
}
// [0, "a"]
// [1, "b"]
// [2, "c"]
fill()
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。(前闭后开)
fill
方法接受三个参数value
,start
以及end
.start
和end
参数是可选的, 其默认值分别为0
和this
对象的length
属性值;fill
方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
var array = [1, 2, 3, 4];
// fill with 0 from position 2 until position 4
console.log(array1.fill('fill', 2, 4)); // [1, 2, "fill", "fill"]
console.log(array); // [1, 2, "fill", "fill"]
find()
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回undefined
。find
方法对数组中的每一项元素执行一次callback
函数,callback
函数带有3个参数:当前元素的值、当前元素的索引,以及数组本身。
findIndex()
用法和他一样,不同的是findIndex()
返回数组中找到的元素的索引,而不是其值。如果找不到,则返回-1。
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true
,否则返回false
。
var array1 = [1, 2, 3];
console.log(array1.includes(2));
// true
var pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// true
includes()
方法有意设计为通用方法。它不要求this
值是数组对象,所以它可以被用于其他类型的对象 (比如类数组对象)。下面的例子展示了 在函数的arguments
对象上调用的includes()
方法。
(function() {
console.log([].includes.call(arguments, 'a')); // true
console.log([].includes.call(arguments, 'd')); // false
})('a','b','c');
实验中的功能
flat()
flat() 方法会递归到指定深度将所有子数组连接,并返回一个新数组。
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
参考
- JavaScript高级程序设计(第三版) Nicholas C.Zakas
- Array.prototype.entries() | MDN
- Array.prototype.fill() | MDN
- Array.prototype.find() | MDN
- Array.prototype.flat() | MDN
- Array.prototype.includes() | MDN