《JavaScript 高级程序设计》这本书被称为 JavaScript 编程的圣经,又称为红宝书。记得这本书是我在刚学前端那会和犀牛书一起购买的,这期间断断续续翻了翻,大部分都处于落灰状态。
这本书很经典,关于 JavaScript 编程的方方面面基本上都讲到了,要是能够通读一遍,可以省去一些翻文档和查资料的时间,这本书的内容也是挺丰盛的,因此我专门建了一个文集,用来做一些读书笔记,以在忘记某块知识时能够回头翻一翻。
判断数组
关于判断数组,这里总结两种方式:
1.使用 Object
原型链上的 toString
方法判断:
function isArray(arr){
return Object.prototype.toString.call(arr).indexOf("Array") !== -1
}
isArray([]) // true
isArray({}) // false
2.使用 Array
对象上原生的 isArray
方法:
Array.isArray([]) //true
Array.isArray({}) //false
数组的 toString
方法
调用数组的 toString
方法,会依次调用数组每一项的 toString
方法,然后将返回值使用逗号进行拼接:
const arr = [{a:1},[],1,2,"hello"]
arr.toString() // "[object Object],,1,2,hello"
同理,调用数组的 toLocaleString
和 valueOf
方法时也会依次调用数组各项元素的 toLocaleString
或 valueOf
方法,然后使用逗号进行拼接。
我们也可以修改数组各项元素的 toString
方法,以取代默认结果:
let ele1 = {
name:"ele1",
toString(){
return "么么哒"
}
}
let ele2 = {
name:"ele2",
toString(){
return "呵呵哒"
}
}
const arr = [ele1,ele2]
arr.toString() //"么么哒,呵呵哒"
对于数组的 toLocaleString
和 valueOf
方法同样适用。
栈/队列方法
我们可以使用数组来模拟栈或者队列数据结构。
栈方法:push
和 pop
:
let arr = []
arr.push(1,2)
arr.pop() //2
arr.pop() //1
对列方法:push
和 shift
:
let arr = []
arr.push(1,2)
arr.shift() //1
arr.shift() //2
反向队列:unshift
和 pop
:
let arr = []
arr.unshift(1,2)
arr.pop() //2
arr.pop() //1
排序方法
1.reverse
方法:
该方法用来对数组进行反转:
let arr = [1,2,3]
arr.reverse() // [3,2,1]
2.sort
方法
该方法用来对数组进行排序,默认按照升序排序,并且在排序时通过元素的 toString
进行位置比较。
因此下面的排序可能不是我们想要的结果:
let arr = [1,2,10,3,20]
arr.sort() //[1,10,2,20,3]
除此之外,sort
方法可以接受一个函数作为参数,用来自定义排序规则。
该参数函数接受两个待比较的元素作为参数,函数返回值决定了这两个元素的排序:
- 返回值小于 0,升序
- 返回值大于 0,降序
- 返回值等于 0,表示这两个参数相等,按照参数顺序排序
let arr = [1,2,10,20,3]
arr.sort((prev,next) => prev - next) // [1, 2, 3, 10, 20]
以上的方法适用于元素的 valueOf
方法返回数值(或者可以隐式转换为数值)的情况,因为只有数值才可以做减法的。如果元素的 valueOf
方法返回的不是数值(或者可以隐式转换为数值),就需要我们手动进行判断,然后进行返回:
let arr = [{val:1},{val:2},{val:10},{val:20},{val:3}]
arr.sort((prev,next) => {
return prev.val - next.val
}) // [{val:1},{val:2},{val:3},{val:10},{val:20}]
注意:reverse
和 sort
方法都会在原始的数组上进行修改。
操作方法
1.concat
方法
该方法用来进行数组合并,接受的参数如下:
- 无参数:返回一个当前数组的副本
- 参数为一个或多个变量、数组:合并当前数组和参数元素,返回合并后的数组
如果参数中含有数组,则会将该数组拆开,并合并到新数组中。
[].concat(1,2,[3,[4,5]]) //[1,2,3,[4,5]]
该方法不会对原始数组进行修改。
2.slice
方法
该方法用来从原始数组中截取一部分元素,基于这些元素再创建一个新数组。
slice
方法的参数:
- 起始位置:截取数组时的起始位置,可为负数,可选,默认为0
- 结束位置:截取数组时的结束位置,可为负数,可选,默认为数组的长度
当 slice
的参数为负数时,该参数和数组长度的和就是实际截取时的启示/结束位置,如果结束位置(经计算转化后)小于起始位置(经计算转化后),则返回一个空数组。
[1,2,3].slice() //[1,2,3]
[1,2,3].slice(1) //[2,3]
[1,2,3].slice(-2,-1) //[2]
[1,2,3].slice(-1,-2) //[]
...
slice
方法不会修改原始数组。
3.splice
方法
该方法较强大,可以用来删除、插入、替换数组元素。该方法会对原始数组进行修改。
1)删除元素
使用 splice
方法删除数组元素需要两个参数:
- 删除元素的起始位置
- 删除元素的个数
返回被删除的元素组成的数组。
let arr = [1,2,3]
arr.splice(0,1) //[1]
arr //[2,3]
2)插入元素
使用 splice
方法插入元素需要至少三个参数:
- 插入的起始位置
- 0 (表示不删除元素)
- 插入的元素序列,可为多个
由于没有删除元素,因此调用该方法返回一个空数组
let arr = [1,2,3]
arr.splice(0,0,"memeda","heheda") //[]
arr // ["memeda", "heheda", 1, 2, 3]
3)替换元素
使用 splice
方法替换元素的原理是先删除该元素,在在其位置上进行替换,在替换时可以使用多个元素序列。
let arr = [1,2,3]
arr.splice(1,1,"memeda","heheda") //[2]
arr //[1, "memeda", "heheda", 3]
位置方法
数组中有两个位置方法:indexOf
和 lastIndexOf
,这两个方法用来查找元素在数组中的位置。indexOf
是从数组开头开始寻找,找到第一个匹配的元素便停止,如果没有匹配到元素,则返回 -1,lastIndexOf
从数组的结尾开始寻找,匹配方式类似。
需要注意的是,indexOf
和 lastIndexOf
匹配元素时要求严格相等(===)。
另外,这两个方法还可以接受起始位置和结束位置两个参数(可选),表示搜寻的位置。
let person = {name:"MIKE"}
let arr1 = [{name:"MIKE"}]
let arr2 = [person]
arr1.indexOf(person) //-1
arr2.indexOf(person) //0
由于使用 indexOf
和 lastIndexOf
方法匹配元素时要求严格相等,因此 arr1
数组并不能匹配到 person
对象。
迭代方法
数组还有几个迭代方法,用来对数组内部的元素做一些迭代操作,这些方法都接受一个函数作为参数,每次进行迭代时都会执行该函数。该函数的参数为:值、位置、原数组
1.every
方法
该方法用来对数组的每一项进行迭代,如果函数对每一个元素都返回 true
,则 every
的返回结果为 true
。
[1,2,3].every((v)=> v>0) //true
[1,2,3].every((v)=> v>1) //false
2.some
方法
该方法和 every
方法类似,但不要求函数对每一个元素返回 true
,只要有一个元素在迭代时返回 true
,some
方法就返回 true
。
true
,则 every
的返回结果为 true
。
[1,2,3].some((v)=> v>0) //true
[1,2,3].some((v)=> v>1) //true
3.filter
方法
该方法用来对数组的每一项进行过滤,返回符合要求的元素列表.
[1,2,3].filter(v=>v%2) //[1,2]
4.forEach
方法
该方法用来对数组的每一项进行操作,该方法没有返回值,也不会影响原始数组,类似于普通的 for
循环。
[1,2,3].forEach(v=>{ console.log(v) }) // 1,2,3
5.map
方法
该方法用来对数组的每一项进行操作,然后将操作的结果映射到一个新数组。
[1,2,3].map(v=>v*2) //[2,4,6]
归并方法
数组还有两个归并方法:reduce
和 reduceRight
。
这两个方法会对数组的每一项进行迭代,然后构建一个最终的返回值。可以接受四个参数:
- 前一个值
- 后一个值
- 当前索引
- 原数组对象
在迭代的过程中,函数的返回值会作为第一个参数传入下一次的迭代的函数中,并最终返回一个最终值。在第一次进行迭代时,前一个参数和后一个参数分别是数组的第一个元素和第二个元素。
reduceRight
从数组的末尾开始归并,其他和 reduce
一致。
// 对数组的每一项相乘
[1,2,3,4,5].reduce((prev,next) => prev * next) //120
[1,2,3,4,5].reduceRight((prev,next) => prev + next) //15
当涉及到对数组元素的累加、累积等操作时,这两个方法很好用。
完。