A programmer who doesn’t use an array well is not a good one, I said~
I took over a project some time ago. The logic was obscure and the code was huge and redundant, making it extremely difficult to get started. The big reason is that the array method is not proficient, which leads to a lot of garbage code. In fact, many places can become simple, efficient and elegant with a little modification. Therefore, I will summarize here the common methods of arrays and KitKat's kinky skills (KitKat's kinky skills are mainly reduce~).
Array operations must first be noted and remember splice、sort、reverse
that these three common methods are operations on the array itself, which will change the array itself. Other methods that will change itself are additions push/pop/unshift/shift
, deletions , filling, fill
and duplication and filling copyWithin
.
Let's talk about the common methods of arrays first, and then talk about the misunderstanding of using them.
Array common methods
First present an array method lazy figure to sacrifice to the sky! (Except for the Array.keys()/Array.values()/Array.entries()
basics):
Encyclopedia of Array Methods
Generate an array like [1-100]:
When testing a large amount of array data, you can:
let arr = new Array(100).fill(0).map((item, index) => index + 1)
Array destructuring assignment application
// 交换变量
[a, b] = [b, a]
[o.a, o.b] = [o.b, o.a]
// 生成剩余数组
const [a, ...rest] = [...'asdf'] // a:'a',rest: ["s", "d", "f"]
Shallow copy of array
const arr = [1, 2, 3]
const arrClone = [...arr]
// 对象也可以这样浅拷贝
const obj = { a: 1 }
const objClone = { ...obj }
There are many shallow copy methods arr.slice(0, arr.length)/Arror.from(arr)
, but ...
after using the operator, you won't want to use others~
Array merge
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [7, 8, 9]
const arr = [...arr1, ...arr2, ...arr3]
arr1.concat(arr2, arr3)
It can also be merged, but ...
after using the operator, you won't want to use other ones~
Array deduplication
const arr = [1, 1, 2, 2, 3, 4, 5, 5]
const newArr = [...new Set(arr)]
new Set(arr)
Accepts an array parameter and generates a set structure data type. Elements of the set data type will not be repeated and yes Array Iterator
, so you can use this feature to remove duplication .
Array intersection
const a = [0, 1, 2, 3, 4, 5]
const b = [3, 4, 5, 6, 7, 8]
const duplicatedValues = [...new Set(a)].filter(item => b.includes(item))
duplicatedValues // [3, 4, 5]
Array subtraction
const a = [0, 1, 2, 3, 4, 5]
const b = [3, 4, 5, 6, 7, 8]
const diffValues = [...new Set([...a, ...b])].filter(item => !b.includes(item) || !a.includes(item)) // [0, 1, 2, 6, 7, 8]
Array to object
const arr = [1, 2, 3, 4]
const newObj = {...arr} // {0: 1, 1: 2, 2: 3, 3: 4}
const obj = {0: 0, 1: 1, 2: 2, length 3}
// 对象转数组不能用展开操作符,因为展开操作符必须用在可迭代对象上
let newArr = [...obj] // Uncaught TypeError: object is not iterable...
// 可以使用Array.form()将类数组对象转为数组
let newArr = Array.from(obj) // [0, 1, 2]
Array common traversal
Arrays are commonly traversed and there are forEach、every、some、filter、map、reduce、reduceRight、find、findIndex
other methods, and many methods can achieve the same effect. The array method must not only be used, but also be used well. To use it well, you need to know when and what method to use.
Mixed use of traversal
filter
The map
return value of the method is still an array, so it can be mixed with other array traversal methods. Note that the more traversal, the lower the efficiency~
const arr = [1, 2, 3, 4, 5]
const value = arr
.map(item => item * 3)
.filter(item => item % 2 === 0)
.map(item => item + 1)
.reduce((prev, curr) => prev + curr, 0)
Check whether all elements of the array meet the judgment conditions
const arr = [1, 2, 3, 4, 5]
const isAllNum = arr.every(item => typeof item === 'number')
Check whether any element of the array meets the judgment condition
const arr = [1, 2, 3, 4, 5]
const hasNum = arr.some(item => typeof item === 'number')
Find the first element/subscript that meets the criteria
const arr = [1, 2, 3, 4, 5]
const findItem = arr.find(item => item === 3) // 返回子项
const findIndex = arr.findIndex(item => item === 3) // 返回子项的下标
Misunderstanding of Array Usage
There are many methods for arrays, and many methods can achieve the same effect, so use the appropriate method according to your needs.
A major cause of garbage code is improper use of common methods of arrays. Here are some points to note:
array.includes() 和 array.indexOf()
array.includes()
Returns a boolean value, array.indexOf()
returns the index of an array item. indexOf
Be sure to use it when an index value is required.
const arr = [1, 2, 3, 4, 5]
// 使用indexOf,需要用到索引值
const index = arr.indexOf(1) // 0
if (~index) { // 若index === -1,~index得到0,判断不成立;若index不为-1,则~index得到非0,判断成立。
arr.spilce(index, 1)
}
// 使用includes,不需要用到索引值
// 此时若用indexOf会造成上下文上的阅读负担:到底其他地方有没有用到这个index?
const isExist = arr.includes(6) // true
if (!isExist) {
arr.push(6)
}
array.find() 、 array.findIndex() 和 array.some()
array.find()
The return value is the first eligible array item, the index of the first eligible array item is array.findIndex()
returned, and the item with array.some()
or without compound conditions is returned true
, if there is any return , if there is no return false
. Note that these three are all short-circuit operations, that is, the traversal will not continue after finding the qualified one.
It is used when the sub-items of the array is array.find()
needed; when the index value of the sub-item array.findIndex()
is needed; and if only the sub-items that meet the conditions need to be known, it is used array.some()
.
const arr = [{label: '男', value: 0}, {label: '女', value: 1}, {label: '不男不女', value: 2}]
// 使用some
const isExist = arr.some(item => item.value === 2)
if (isExist) {
console.log('哈哈哈找到了')
}
// 使用find
const item = arr.find(item => item.value === 2)
if (item) {
console.log(item.label)
}
// 使用findIndex
const index = arr.findIndex(item => item.value === 2)
if (~index) {
const delItem = arr[index]
arr.splice(index, 1)
console.log(`你删除了${delItem.label}`)
}
It is recommended to use when only Boolean values are needed and when the array items are strings or numbers array.some()
:
// 当子包含数字0的时候可能出错
const arr = [0, 1, 2, 3, 4]
// 正确
const isExist = arr.some(item => item === 0)
if (isExist) {
console.log('存在要找的子项,很舒服~')
}
// 错误
const isExist = arr.find(item => item === 0)
if (isExist) { // isExist此时是0,隐式转换为布尔值后是false
console.log('执行不到这里~')
}
// 当子项包含空字符串的时候也可能出错
const arr = ['', 'asdf', 'qwer', '...']
// 正确
const isExist = arr.some(item => item === '')
if (isExist) {
console.log('存在要找的子项,很舒服~')
}
// 错误
const isExist = arr.find(item => item === '')
if (isExist) { // isExist此时是'',隐式转换为布尔值后是false
console.log('执行不到这里~')
}
array.find() 和 array.filter()
Just know that what is array.filter()
returned is an array composed of all eligible sub-items, and all arrays will be traversed; and array.find()
only the first eligible sub-item is returned, which is a short-circuit operation. No more examples~
Reasonable use of Set data structure
Because es6 natively provides a Set
data structure, it Set
can ensure that the sub-items are not repeated, and it is very convenient to convert with the array, so in some scenarios that may involve repeated addition, it can be directly used Set
instead Array
, avoiding multiple places to repeatedly determine whether the existing Child.
const set = new Set()
set.add(1)
set.add(1)
set.add(1)
set.size // 1
const arr = [...set] // arr: [1]
Powerful reduce
array.reduce
Traverse and use the return value of the current callback function as the first parameter of the next callback function execution.
Using to array.reduce
replace some scenes that need to be traversed multiple times can improve the efficiency of code operation.
Suppose there is an array composed of the letter's' plus a number for each element as follows arr
, and now find the largest number in it: ( arr
not empty)
const arr = ['s0', 's4', 's1', 's2', 's8', 's3']
// 方法1 进行了多次遍历,低效
const newArr = arr.map(item => item.substring(1)).map(item => Number(item))
const maxS = Math.max(...newArr)
// 方法2 一次遍历
const maxS = arr.reduce((prev, cur) => {
const curIndex = Number(cur.replace('s', ''))
return curIndex > prev ? curIndex : prev
}, 0)
const arr = [1, 2, 3, 4, 5]
// 方法1 遍历了两次,效率低
const value = arr.filter(item => item % 2 === 0).map(item => ({ value: item }))
// 方法1 一次遍历,效率高
const value = arr.reduce((prev, curr) => {
return curr % 2 === 0 ? [...prev, curr] : prev
}, [])
You can also use reduce to do the following processing to generate the desired html structure:
// 后端返回数据
const data = {
'if _ then s9': [
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生',
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生',
'作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生'
],
'if C then s4': [
'当有条件时时,结构构件满足要求,要求属于安全性、适用性和耐久性',
'当有条件时时,住宅结构满足要求,要求属于安全性、适用性和耐久性'
]
}
const ifthens = Object.entries(data).reduce((prev, cur) => {
const values = cur[1].reduce((prev, cur) => `${prev}<p>${cur}</p>`, '')
return `
${prev}
<li>
<p>${cur[0]}</p>
${values}
</li>
`
}, '')
const html = `
<ul class="nlp-notify-body">
${ifthens}
</ul>
`
The generated html structure is as follows:
<ul class="nlp-notify-body">
<li>
<p>if _ then s9</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
<p>作用属于各种,结构属于住宅,结构能承受作用,作用属于在正常建造和正常使用过程中可能发生</p>
</li>
<li>
<p>if C then s4</p>
<p>当有条件时时,结构构件满足要求,要求属于安全性、适用性和耐久性</p>
<p>当有条件时时,住宅结构满足要求,要求属于安全性、适用性和耐久性</p>
</li>
</ul>