Array对象及原型
JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。本文将主要讲解 Array.prototype
下的方法
fill
用一个固定值填充一个数组中从起始索引到终止索引内的全部元素,不包括终止索引。
语法:
arr.fill(value[, start[, end]])value
用来填充数组元素的值。start
起始索引,默认值为 0。end
终止索引,默认值为 this.length。
1 | new Array(5).fill(1); // [1, 1, 1, 1,1] |
splice
可删除或添加新的元素来修改原数组,返回被删除的元素组成的一个数组,如果没有删除元素,则返回空数组。
array.splice(start[, deleteCount[, item1[, item2[, …]]]])start
指定修改的开始位置deleteCount
要移除的数组元素的个数item1, item2, ...
从start 位置开始,添加进数组的元素
1 | var arr = [1, 2, 3, 4] |
copyWithin
浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。
arr.copyWithin(target[, start[, end]])target
复制到该位置的索引start
可选,开始复制元素的起始位置end
可选,开始复制元素的结束位置
1 | var arr = [1, 2, 3, 4, 5]; |
some
测试是否至少有一个元素可以符合条件,也就是被提供的函数返回true。some()
为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some() 将会立即返回 true,否则,都不符合条件,返回 false。
1 | [1, 2, 3, 0].some(v => !v) |
every
跟 some 不一样,every 检测一个数组内的所有元素是否都能通过某个指定函数的测试,并返回布尔值。如果某个元素使 callback 返回 false,则循环终止,every 立即返回false,否则,返回 true。
注意:空数组情况下返回true。every 和数学中的"所有"类似,当所有的元素都符合条件才会返回true。正因如此,若传入一个空数组,无论如何都会返回 true。(这种情况属于无条件正确:正因为一个空集合没有元素,所以它其中的所有元素都符合给定的条件。)
1 | [1, 2, 3, 0].every(v => !v) |
includes
用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回false。
注意:对象数组不能使用includes方法来检测。
1 | [1, 2, 3].includes(2); |
map
map 方法会循环遍历数组,对每一个元素进行函数式的处理。注意:原来数组不会发生变化,会返回一个新的数组。
比如有这样一个函数f(x)=x*x
,用 map 实现如下:
1 | var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; |
运行结果:[1, 4, 9, 16, 25, 36, 49, 64, 81]
此功能完全可以自己封装一个函数来完成,但是不容易一眼就看出是函数作用于元素,也就是可读性不高。map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以f(x)=x*x
,还可以计算任意复杂的函数。
此方法还可以转换数组元素类型:
1 | var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; |
运行结果: [“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”]
把字符串转化为数组:
1 | Array.prototype.map.call("String", function(x) { |
运行结果:[“S”, “t”, “r”, “i”, “n”, “g”]
map 和 forEach 异同点:
- map 和 forEach 非常相似,都是用来遍历数组中的每一项,并不对原数组进行修改;
- 区别在于 map 支持 return 返回(返回的是进行修改后的原数组的克隆版本),而 forEach 不支持;
- 两者都支持第二个参数,这第二个参数的意思是把匿名回调函数中的 this 进行修改。
1 | var obj = { key: 12 }; |
运行结果:[12, 24, 36]
reduce
直接上代码,看看运行结果:
1 | var arr = [1, 2, 3, 4, 5]; |
运行结果:
1 | 1 2 1 |
reduce
回调函数中有四个参数:
res: 第一项的值或者上一次叠加的结果值
cur: 当前会参与叠加的项
index:当前参与叠加项的索引
self: 数组本身
从这个例子可以看出reduce
能实现累加运算,那么能进行累积运算吗,当然可以,这个自己下去试试就知道了。
给 reduce 参数添加第二个参数,通过打印我发现,reduce
会遍历 5 次。
1 | var arr = [1, 2, 3, 4, 5]; |
运行结果:
1 | 0 1 0 |
这第二个参数就是设置 res 的数据类型和初始值,设置为 0,就表示 res 的初始值为number
类型,值为 0,因此,reduce
的最终结果也会是number
类型。
那么,如何计算一串字符串中每个字母出现的次数呢?
1 | var str = "abcdaabce"; |
运行结果:{a: 3, b: 2, c: 2, d: 1, e: 1}
由于可以通过第二个参数设置叠加结果的类型和初始值,我们可以灵活的运用它来进行各种各样的类型转换,比如将数组按照一定规则转换为对象,也可以将一种形式的数组转换为另一种形式的数组。
这种特性使得reduce
在实际开发中大有可为!但是需要注意点,在 IE9 以下的浏览器中,并不支持该方法!
应用:
reduce
还可以去除字符串中的重复字符,类似于数组去重
1 | var str = "abc12122adc"; |
- 递归方法将多维数组转一维:
1 | var arr = [1, [2, 3, 4], [[5, 6], 7], 8]; |
- 将树形json结构扁平化
1 | // reduce 第二个参数为当前参与计算的项,也就是数组的某个元素 (Object) |
Json:
1 | [ |
filter
顾名思义,它用于过滤某些元素,返回剩下的元素。和 map()有点类似,filter()也接收一个函数。和 map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是 true 还是 false 决定保留还是丢弃该元素。
1 | var s = "i love you very very very much,do you love me?"; |
运行结果:[“i”, “love”, “you”, “very”, “much”, “do”, “me”]
ele: 当前遍历的数组元素
index:当前遍历元素的位置
self: 数组本身
由此可看出filter
和reduce
的去重效果是一样的,不过这种方法更简洁,逻辑更清晰。
其实还有更简便的方法:
1 | Array.from(new Set(arr)); //ES6 |
参考文档:Array 方法