锋利的ES6 — 数组API
锋利的ES6 系列文章介绍ES6(ES5+)中新增的比较好用的新特性。本篇聊聊数组API以及使用这些API来改造todolist(待办事项列表),文末附有Git地址。
目录
forEach(ES5)
遍历数组,没有返回值,稀疏数组中的undefined
被过滤掉,但是索引还是正常值。
1 | var arr = ['Dary', 'Tom', 'Jim', , 'Lom'] |
需要指出的是:
在遍历的回调函数里的第三个参数array指的就是当前正在遍历的数组
1
2
3
4var arr = ['Dary', 'Tom', 'Jim', , 'Lom']
arr.forEach(function (item, index, array) {
// array就是arr本身
})forEach除了传一个回调函数以外,后面还有可选的第二个参数,传递一个对象,这样在遍历的时候this就指向这个对象
1
2
3
4var arr = ['Dary', 'Tom', 'Jim', , 'Lom']
arr.forEach(function (item, index) {
// 这里的this就指向document
}, document)
但是一般不会在这里对数组进行操作,forEach就单纯的负责遍历数组,如果要对数组做操作可以使用下面介绍的一些方法
map(ES5)
遍历的同时返回一个新的数组,由每趟遍历的回调函数里返回值组成,一般可以用于对数组里的数据做修改。需要特别指出的是每一次遍历都要返回一个结果,否则最后你会得到一个稀疏数组。
1 | var arr = [1, 4, 9, 16] |
当然,这里的回调里也是有第三个参数指当前数组本身,回调后面也有第二个可选参数绑定this指向的,这里就不赘述了。
map方法一般用来修改数组,可以修改整个数组也可以根据一些条件修改数组中的某个值
filter(ES5)
过滤,遍历的同时返回一个新的数组。在回调函数里返回一个条件,满足条件的数据会被保留,不满足的被过滤掉。
1 | const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'] |
毫无疑问,这个方法的回调里也有第三个参数以及回调后面的参数。
这个方法一般用于删除数组元素
some(ES5)
返回一个布尔值,在回调函数里返回一个条件,只要在遍历的过程中有任意一条数据满足条件,就终止遍历,并且最终得到的值就是true,否则会一直遍历到结束,最终得到false
1 | const arr = [1, 2, 3, 4, 5] |
这个方法也有上述方法提到过的可选参数
every(ES5)
返回一个布尔值,在回调函数里返回一个条件,在遍历的过程中只要有一条数据不满足条件,就终止遍历,并且最终得到false,否则会一直遍历到结束,最终得到true
1 | const arr = [1, 30, 39, 29, 10, 13]; |
这个方法也有上述方法提到过的可选参数
reduce、reduceRight(ES5)
归并,返回一个新值,在每一趟遍历时返回一个值,这个值会继续作为下一次遍历的初始值来使用,最终遍历完成得到最后返回的值。一般在处理整个数组需要最终得到一个值的情况下使用,比如计算总价,合并数组等。
reduce是从左往右归并,而reduceRight是从右往左,只是顺序不一样并不影响结果,reduceRight一般用的很少。
1 | var arr = [1, 2, 3, 4] |
reduce很多时候都会用到初始值,尤其在操作json数组的时候极为有用,比如计算商品总价
1 | var list = [ |
reduce的回调里还有另外两个可选参数index和array
1 | var arr = [1, 2, 3, 4] |
from(ES6)
这是Array对象本身的方法,所以调用方式是Array.from()
,它可以将一个可迭代对象,例如NodeList、classList等转换成一个数组
1 | Array.from(document.querySelesctorAll('.delete')) |
includes(ES2016)
实验性的API,包含,返回一个布尔值,判断一个数组里是否包含某个值,比indexOf更好用的是直接得到布尔值而不用去判断返回值是否为-1(注:其实indexOf也是属于ES5的语法,但是由于平时用的非常频繁,这里就不单独提出来讲了)
1 | // 结合Array.from判断元素是否含有某个class非常方便 |
copyWithin(ES6)
实验性的API,复制数组中的一部分值,返回一个新的数组,新数组的长度和原数组一致
第一个参数是目标位置
第二三个参数是copy的区间
1 | // 将数组复制到-2(即索引3)的位置,结果为 [1, 2, 3, 1, 2] |
keys(ES6)
实验性的API,返回一个新的Array Iterator对象,该迭代器会包含所有数组元素的键
1 | const array1 = ['a', 'b', 'c']; |
values(ES6)
实验性的API,返回一个新的Array Iterator对象,该迭代器含数组每个索引的值
1 | const array1 = ['a', 'b', 'c']; |
entries(ES6)
实验性的API,返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对
1 | const array1 = ['a', 'b', 'c']; |
fill(ES6)
实验性的API,指定值和索引来填充数组
1 | const array1 = [1, 2, 3, 4]; |
flat(ES2019)
将多维数组扁平化
1 | var arr1 = [1, 2, [3, 4]]; |
flatMap
草案,还没有标准化,使用方式跟map方法类似,不过这个方法回调里需要返回数组,最终会把每一趟返回的数组concat器来作为这个方法的结果。在一趟遍历需要得到两个值的时候比较有用
1 | var arr1 = [1, 2, 3, 4]; |
写一个todolist
接下来我们就使用刚学的这些API来改造todolist
首先,从所有的todos中筛选出已完成和未完成我们可以使用filter
改造前:
1
2
3
4
5
6
7
8var hasFinishedTodos = []
for (var i = 0; i < todos.length; i++) {
if (todos[i].hasFinished) hasFinishedTodos.push(todos[i])
}
var unFinishedTodos = []
for (var i = 0; i < todos.length; i++) {
if (!todos[i].hasFinished) unFinishedTodos.push(todos[i])
}改造后:
1
2
3
4
5
6var hasFinishedTodos = todos.filter(function (todo) {
return todo.hasFinished
})
var unFinishedTodos = todos.filter(function (todo) {
return !todo.hasFinished
})计算未完成事项的总时间,可以使用reduce
改造前:
1
2
3
4var hours = 0
for (var i = 0; i < unFinishedTodos.length; i++) {
hours += unFinishedTodos[i].time
}改造前:
1
2
3var hours = unFinishedTodos.reduce(function (time, todo) {
return time + todo.time
}, 0)循环数组拼接html字符串可以使用reduce
改造前:
1
2
3
4
5
6
7var hasFinishHTML = ''
for (var i = 0; i < hasFinishedTodos.length; i++) {
hasFinishHTML += '<div class="column is-one-quarter" data-id="${todo.id}">'+
'...'+
'</div>'
}
document.querySelector('#has-finish-wrap').innerHTML = hasFinishHTML改造后:
1
2
3
4
5
6document.querySelector('#has-finish-wrap').innerHTML =
hasFinishedTodos.reduce(function (html, todo) {
return html + '<div class="column is-one-quarter" data-id="${todo.id}">'+
'...'+
'</div>'
}, '')事件委托通过class判断事件源可以使用Array.from和includes配合
改造前:
1
2
3
4var arrClass = e.target.className.split(/\s+/)
if (arrClass.indexOf('btn-toggle') !== -1) {
// ...
}改造后:
1
2
3if (Array.from(e.target.classList).includes('btn-toggle')) {
// ...
}切换完成状态修改数组可以使用map
改造前:
1
2
3for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) todos[i].hasFinished = !todos[i].hasFinished
}改造后:
1
2
3
4todos = todos.map(function (todo) {
if (todo.id === id) todo.hasFinished = !todo.hasFinished
return todo
})删除待办事项可以使用filter
改造前:
1
2
3
4
5
6for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todos.splice(i, 1)
i--
}
}改造后:
1
2
3todos = todos.filter(function (todo) {
return todo.id !== id
})
todolist(待办事项列表)案例将在我的github上持续更新
欢迎star!!!
代码不是万能的,但不写代码是万万不能的
Dary记
-
更多干货,尽在公众号
转载请注明来源,文末有原始链接。欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 dary1112@foxmail.com
创作不易,您的打赏是我更新的动力
-
支付宝
-
微信
文章标题:锋利的ES6 — 数组API
文章字数:2.6k
本文作者:Dary
发布时间:2020-03-14, 10:04:00
最后更新:2020-03-16, 15:19:32
原始链接:http://www.xiongdalin.com/2020/03/14/ES6-array/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。
Built By Dary