JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
前言
在之前已经学习了一些数组的属性和方法:
arr.length
:返回数组的长度。arr.push(...items)
:从尾端添加元素,arr.pop()
:从尾端提取元素,arr.shift()
:从首端提取元素,arr.unshift(...items)
:从首端添加元素。
以下的章节再深入学习一些常用的属性或方法。
$$tip
完整的属性和方法请查阅 Array - MDN。
$$
数组的判断
判断变量是否是数组
由于数组属于对象下的类型,因此使用 typeof
不能判断一个变量是否是数组。要判断一个变量是否是数组通常有以下两种方法:
- instanceof 运算符
- Array.isArray 方法
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
alert(typeof arr) // object
alert(Array.isArray(arr)) // true
alert(arr instanceof Array) // true
判断数组是否相等
很遗憾, ==
运算符并不能帮我们判断两个数组的值是否相等,它只能判断是否是同一个数组的㳀拷贝。
$$tip
浅拷贝的概念将在后面章节学习到。
$$
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
let arr2 = [1, 2, 3]
alert(arr == arr2) // false
let arr3 = arr
alert(arr == arr3) // true
常用属性和方法
数组长度
length
属性可以返回当前数组的长度。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
alert(arr.length) // 3
如果通过下标给数组赋值时下标超过了当前数组的长度,未赋值的下标取值为 undefined
。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
arr[5] = "end"
alert(arr.length) // 6
alert(arr[3]) // undefined
alert(arr[4]) // undefined
alert(arr[5]) // "end"
length
是一个可写的属性值,如果改变其的值,当 length
比原值大时,未赋值的下标取值为 undefined
,当 length
比原值小时则会截取数组。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3, 4, 5]
arr.length = 10
console.log(arr) // [1, 2, 3, 4, 5, 空属性 × 5]
arr.length = 2
console.log(arr) // [1, 2]
合并数组
concat(value1[, ... valueN])
用于合并多个数组或值并返回一个拼接后的新数组。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
alert(arr.concat([4, 5], 6, 7)) // 1,2,3,4,5,6,7
截取数组
slice([begin[, end]])
方法返回截取后的新数组:
- begin:开始下标(包含),可选参数,默认值为
0
。如果为负数则表示倒数第 N 个元素,例如 -3 表示从倒数第三个元素开始截取。 - end:结束下标(不包含),可选参数,默认值为数组长度,如果为负数则表示倒数第 N 个元素。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
alert(arr.slice(1, 3)) // 眼, 鸭
删除元素
delete
运算符可以删除数组中任意下标的元素,但是删除后的数组长度不变,只是对应下标的取值为 undefined
。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭"]
delete arr[1]
alert(arr.length) // 3
alert(arr[1]) // undefined
修改数组
splice(start[, deleteCount[, item1[, ... itemN]]])
可以从指定的下标开始移除指定数量的元素,并插入新元素。
- start:修改位置的开始下标,如果是负数则表示倒数第 N 个元素。
- deleteCount:移除元素的个数,可选参数,如果省略则移除 start 起至结尾的所有元素。
- item:添加的新元素,可选参数。
- return:返回值为移除的元素数组。
$$warning
与很多已学的方法不同, splice
会修改原数组而不是返回一个新数组。
$$
删除指定下标开始指定个数的元素。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
let result = arr.splice(4, 2)
alert(result) // 编,程
alert(arr) // 三,眼,鸭,的,教,室
在指定的下标插入多个元素,不删除元素的话删除个数的参数传 0
。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
arr.splice(4, 0, "食", "堂")
alert(arr) // 三,眼,鸭,的,食,堂,编,程,教,室
删除元素并同时插入新的元素。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
let result = arr.splice(4, 2, "食", "堂")
alert(result) // 编,程
alert(arr) // 三,眼,鸭,的,食,堂,教,室
$$tip
splice
是一个很灵活的函数,可能通过封装 splice
实现很多高级功能,参考本章练习的第二、三题。
$$
转成字符串
toString()
返回一个用逗号分割元素的字符串,我们使用 alert
显示数组时就是默认使用 toString()
进行转换。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3, 4]
let str = arr.toString()
console.log(typeof str) // string
console.log(str) // 1,2,3,4
join([separator])
方法可以用分隔符来拼接元素元素并返回字符串。
- separator:分隔符,可选参数,默认值为
,
。
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3, 4]
let str = arr.join("-")
console.log(str) // 1-2-3-4
实例:将单词首字母大写
$$jsdemo$$
$$edit$$
function upperWord(str) {
// 先将字符串按照空格分割成数组
let arr = str.split(" ")
for (let i in arr) {
// 将每个单词的首字母大写
arr[i] = arr[i][0].toUpperCase() + arr[i].substring(1)
}
// 重新用空格拼接
return arr.join(" ")
}
let str = "nice to meet you."
alert(upperWord(str)) // Nice To Meet You.
查找数组
判断包含某元素
includes(item)
判断数组中是否存在某个元素,存在返回 true
否则返回 false
。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭"]
alert(arr.includes("鸭")) // true
返回匹配的下标
indexOf(item[, fromIndex])
会在数组中查找指定的元素,返回首个位置下标或 -1。
- item:要查找的元素。
- fromIndex:起始下标,默认值为 0。
$$jsdemo$$
$$edit$$
let arr = ["三", "眼", "鸭"]
alert(arr.indexOf("鸭")) // 2
alert(arr.indexOf("鸡")) // -1
lastIndexOf(item[, fromIndex])
返回的则是最后一个匹配的元素下标。
查找满足特定条件的元素
find(callback)
用于查找并返回第一个满足条件的元素。对数组中的每一项元素执行一次 callback
函数,如果某次 callback
函数返回了 true
,则结束遍历并返回元素的值。如果未有一次返回 true
则最终返回 undefined
。
callback
接收三个参数:
- element:当前遍历的元素。
- index:当前遍历的下标。
- array:数组本身。
$$jsdemo$$
$$edit$$
let scores = [24, 80, 5, 70, 10, 30, 90]
// 返回第一个大于等于 60 的数
let score = scores.find(function (element, index, array) {
if (element >= 60) {
return true
}
return false
})
alert(score) // 80
findIndex(callback)
类似,不过返回的是下标,如果未找到则返回 -1 。
查找满足特定条件的元素并返回数组
filter(callback)
用于查找并返回多个满足条件元素组成的数组。
$$jsdemo$$
$$edit$$
let scores = [24, 80, 5, 70, 10, 30, 90]
// 返回所有大于等于 60 的数
let arr = scores.filter(function (element, index, array) {
if (element >= 60) {
return true
}
return false
})
alert(arr) // 80,70,90
修改元素并返回数组
map(callback)
使用回调函数循环数组中的每一个元素,并将函数的返回值作为元素返回新数组。
callback
接收三个参数:
- element:当前遍历的元素。
- index:当前遍历的下标。
- array:数组本身。
以下例子将数组中每个元素乘以 2。
$$jsdemo$$
$$edit$$
let scores = [24, 80, 5, 70, 10, 30, 90]
// 将数组每个元素乘以 2
let arr = scores.map(function (element, index, array) {
return element * 2
})
alert(arr) // 48,160,10,140,20,60,180
反转数组
reverse()
方法可以反转一个数组,此方法会影响原数组。
$$tip
reverse
方法会影响原数组。
$$
$$jsdemo$$
$$edit$$
let arr = [1, 2, 3]
arr.reverse()
alert(arr) // 3,2,1
数组排序
sort([compareFunction])
方法默认按照UTF-16代码单元值序列排序,接收一个可选的比较函数。如果指定了 compareFunction
函数则使用其进行排序。
compareFunction
函数接收两个参数值 a 、 b 分别是两个比对的元素:
- 如果
compareFunction(a, b)
小于 0 ,那么 a 会被排列到 b 之前。 - 如果
compareFunction(a, b)
大于 0 , b 会被排列到 a 之前。 - 如果
compareFunction(a, b)
等于 0,a、b 的位置不变(不是所有浏览器都会遵守)。
$$tip
sort
方法会影响原数组。
$$
$$jsdemo$$
$$edit$$
let scores = [24, 80, 5, 70, 10, 30, 90]
// 从低到高进行排序
scores.sort(function (a, b) {
if (a < b) {
return -1
} else if (a > b) {
return 1
} else {
return 0
}
})
alert(scores) // 5,10,24,30,70,80,90
简略写法:
$$jsdemo$$
$$edit$$
let scores = [24, 80, 5, 70, 10, 30, 90]
// 从低到高进行排序
scores.sort(function (a, b) {
return a - b
})
alert(scores) // 5,10,24,30,70,80,90
遍历数组
forEach(callback)
方法可以遍历一个数组。
callback
接收三个参数:
- element:当前遍历的元素。
- index:当前遍历的下标。
- array:数组本身。
$$jsdemo$$
$$edit$$
const arr = [10, 18, 5, 22]
arr.forEach(function (element, index, array) {
console.log(element)
})
数组计算
reduce(callback, initialValue)
方法对数组中的每个元素按序执行一个由您提供的 callback
函数,每一次运行 callback
会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
callback
接收三个参数:
previousValue
:上一次调用callbackFn
时的返回值。在第一次调用时,若指定了初始值initialValue
,其值则为initialValue
,否则为数组索引为 0 的元素array[0]
。currentValue
:数组中正在处理的元素。在第一次调用时,若指定了初始值initialValue
,其值则为数组索引为 0 的元素array[0]
,否则为array[1]
。currentIndex
:数组中正在处理的元素的索引。若指定了初始值initialValue
,则起始索引号为 0,否则从索引 1 起始。array
:用于遍历的数组。
initialValue
:可选参数,初始值。
以下实例为求出数组中的最小值。
$$jsdemo$$
$$edit$$
const arr = [10, 18, 5, 22]
const min = arr.reduce(function (previousValue, currentValue) {
return previousValue < currentValue ? previousValue : currentValue
}
)
alert(min) // 5
练习
- 以下代码输出的值是?
const arr = [1, 2, 3]
arr[100] = undefined
alert(arr.length) // ?
$$answer
$$jsdemo$$
$$edit$$
const arr = [1, 2, 3]
arr[100] = undefined
alert(arr.length) // 101,设置超过数组长度的下标会改变数组长度
$$
- 定义一个函数,可以从数组中删除指定的元素。
function removeItem(arr, item) {
// 补全这里
}
const arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
const result = removeItem(arr, "鸭")
console.log(result) // ['三', '眼', '的', '编', '程', '教', '室']
$$answer
$$jsdemo$$
$$edit$$
function removeItem(arr, item) {
let idx = arr.indexOf(item)
if (idx !== -1) {
// -1 代表没找到指定元素
arr.splice(idx, 1)
}
return arr
}
const arr = ["三", "眼", "鸭", "的", "编", "程", "教", "室"]
const result = removeItem(arr, "鸭")
console.log(result) // ['三', '眼', '的', '编', '程', '教', '室']
$$
- 如果你够细心,应该发现上一题只能删除第一个匹配到的元素。修改一下函数,使其能删除所有匹配到的元素。
function removeItemAll(arr, item) {
// 补全这里
}
const arr = ["三", "眼", "鸭", "的", "鸭", "鸭", "教", "室"]
const result = removeItemAll(arr, "鸭")
console.log(result) // ['三', '眼', '的', '教', '室']
$$answer
$$jsdemo$$
$$edit$$
function removeItemAll(arr, item) {
while (true) {
let idx = arr.indexOf(item)
if (idx === -1) {
// -1 代表没找到指定元素
return arr
} else {
arr.splice(idx, 1)
}
}
}
const arr = ["三", "眼", "鸭", "的", "鸭", "鸭", "教", "室"]
const result = removeItemAll(arr, "鸭")
console.log(result) // ['三', '眼', '的', '教', '室']
$$
- 有一个数组记录了班上同学的对象,从中快速找出鸣人对象。
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
// 结果
// {name: '鸣人', score: 38}
$$answer
$$jsdemo$$
$$edit$$
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
const mingren = students.find(function (element, index, array) {
if (element.name === "鸣人") {
return true
}
return false
})
console.log(mingren) // {name: '鸣人', score: 38}
$$
- 从上一题的同学数组中快速找到成绩不合格的同学。
// 结果
// [{name: '鸣人', score: 38}, {name: '路飞', score: 48}]
$$answer
$$jsdemo$$
$$edit$$
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
const fails = students.filter(function (element, index, array) {
if (element.score < 60) {
return true
}
return false
})
// 返回所有不及格的同学
console.log(fails) // [{name: '鸣人', score: 38}, {name: '路飞', score: 48}]
$$
- 针对同学数组,使其按成绩从大到小排列。
// 结果
// [{name: '柯南', score: 98}, {name: '路飞', score: 48}, {name: '鸣人', score: 38}]
$$answer
$$jsdemo$$
$$edit$$
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
// 按成绩从高到低排序
students.sort(function (a, b) {
return b.score - a.score
})
console.log(students) // [{name: '柯南', score: 98}, {name: '路飞', score: 48}, {name: '鸣人', score: 38}]
$$
- 针对同学数组,返回班上所有同学的姓名组成的数组。
// 结果
// ["柯南", "鸣人", "路飞"]
$$answer
$$jsdemo$$
$$edit$$
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
// 获取班上所有同学的姓名组成的数组
let names = students.map(function (element, index, array) {
return element.name
})
console.log(names) // ['柯南', '鸣人', '路飞']
$$
- 针对同学数组,使用
reduce
方法求出班上所有同学的总分。
// 结果
// 184
$$answer
const students = [
{ name: "柯南", score: 98 },
{ name: "鸣人", score: 38 },
{ name: "路飞", score: 48 },
]
const total = students.reduce((pre, item) => pre + item.score, 0)
alert(total) // 184
$$