1. JavaScript 基础

  2. Document

  3. 运算符

  4. 深入数据和类型

  5. 函数进阶

  6. 原型、继承

  7. 浏览器存储

  8. Web API

  9. 事件

  10. 错误处理

  11. 异步编程

  12. 网络请求

  13. 模块

  14. 练习

  15. 实例

  16. 工具与规范

  17. 软件架构模式

  18. 设计模式

前言

在之前已经学习了一些数组的属性和方法:

  • 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

练习

  1. 以下代码输出的值是?
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,设置超过数组长度的下标会改变数组长度

$$

  1. 定义一个函数,可以从数组中删除指定的元素。
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) // ['三', '眼', '的', '编', '程', '教', '室']

$$

  1. 如果你够细心,应该发现上一题只能删除第一个匹配到的元素。修改一下函数,使其能删除所有匹配到的元素。
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) // ['三', '眼', '的', '教', '室']

$$

  1. 有一个数组记录了班上同学的对象,从中快速找出鸣人对象。
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}

$$

  1. 从上一题的同学数组中快速找到成绩不合格的同学。
// 结果
// [{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}]

$$

  1. 针对同学数组,使其按成绩从大到小排列。
// 结果
// [{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}]

$$

  1. 针对同学数组,返回班上所有同学的姓名组成的数组。
// 结果
// ["柯南", "鸣人", "路飞"]

$$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) // ['柯南', '鸣人', '路飞']

$$

  1. 针对同学数组,使用 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

$$