创建和初始化数组
JavaScript 声明, 创建和初始化数组, 如下:
let daysOfWeek = new Array(); // {1}
let daysOfWeek = new Array(7); // {2}
let daysOfWeek = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); // {3}
使用 new 关键字,声明并初始化一个数组 ( 行 {1} ).创建一个指定长度的数组 ( 行 {2} ).将数组元素作为参数传递给它的构造函数 ( 行 {3} ).
更简单的方式创建数组,如下:
let daysOfWeek = []
使用一些元素初始化数组,如下:
let daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
使用数组的 length 属性,查询数组里面的包含多少元素
console.log(daysOfWeek.length);
访问元素和迭代数组
输出数组 daysOfWeek 里的所有元素,通过循环遍历数组,打印元素
for (let i = 0; i < daysOfWeek.length; i++) {
console.log(daysOfWeek[i]);
}
求斐波那契数列的前20个数字. 已知斐波那契数列的第一个数字是1, 第二个是2, 从第三项开始, 每一项都等于前两项之和:
let fibonacci = []
fibonacci[1] = 1
fibonacci[2] = 2
for (let i = 3; i < 20; i++) {
fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2]
}
for (let i = 1; i < fibonacci.length; i++) {
console.log(fibonacci[i])
}
添加元素
一个数组 numbers, 初始化成 0 到 9:
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
如果给数组添加一个元素 (比如10), 把值赋给数组中最后一个空位上的元素即可.
numbers[numbers.length] = 10
在 JavaScript 中, 数组是一个可以修改的对象. 如果添加元素, 它就会动态增长. 在 C 和 Java 等其他语言中, 我们要决定数组的大小, 想添加元素就要创建一个全新的数组, 不能简单地往其中添加所需的元素.
使用 push
push 方法能把元素添加到数组的末尾. 通过 push 方法,能添加任意个元素:
numbers.push(11)
numbers.push(12, 13)
插入元素到数组首位
实现这个需求, 首先要腾出数组里第一个元素的位置, 把所有的元素向右移动一位. 我们可以循环数组中的元素, 从最后一位 +1 (长度) 开始, 将其对应的前一个元素的值赋给它, 依次处理, 最后把我们想要的值赋给第一个位置 (-1) 上.
for (let i = numbers.length; i >=0; i--) {
numbers[i] = numbers[i - 1]
}
numbers[0] = -1
使用 unshift 方法
unshift 方法,可以直接把数值插入数组的首位:
numbers.unshift(-2)
numbers.unshift(-4, -3)
删除元素
删除数组里最靠后的元素,使用 pop
方法
numbers.pop()
通过 push 和 pop 方法,就能用数组模拟栈
从数组首位删除元素
如果移除数组里的第一个元素,可以用下面代码
for (let i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i + 1]
}
可以看到,只是把数组第一位的值用第二位覆盖了,并没有删除元素(数组长度和原来一样,并且多了一个未定义的元素)
使用 shift
方法
要确实删除数组的第一个元素,可以用 shift
方法实现
numbers.shift()
通过 shift 和 unshift 方法,就能用数组模拟基本的队列数据结构
在任意位置添加或删除数组
使用 splice
方法,简单通过指定位置/索引, 就可以删除相应位置和数量的元素
numbers.splice(5, 3)
这行代码删除了从数组索引 5 开始的 3 个元素
对于 JavaScript 数组和对象,还可以用 delete 操作符删除数组中的元素, 例如 delete numbers[0]. 数组位置0 的值会变成 undefined , 也就是说, 以上操作等于 numbers[0] = undefined. 因此, 我们应该始终用 splice, pop 和 shift 方法来删除数组元素
把数字 2, 3, 4 插入数组,放到之前删除元素的位置上, 可以再次使用 splice 方法
numbers.splice(5, 0, 2, 3, 4)
splice 方法接收的第一个参数,表示想要删除或插入的元素的索引值.第二个参数是删除元素的个数(这个例子里, 我们的目的不是删除元素,所以传入0).第三个参数往后,就是要添加到数组里面的值(元素2, 3, 4)
最后执行下面代码
numbers.splice(5, 3, 2, 3, 4)
输出的值是从 -3 到 12. 原因在于, 我们从索引 5 开始删除了 3 个元素, 但也从索引 5 开始添加了元素 2, 3, 4.
二维和多维数组
保存两天的每小时气温
let averageTempDay1 = [72, 75, 79, 79, 81, 81]
let averageTempDay2 = [81, 79, 75, 75, 73, 72]
使用矩阵(二维数组)存储数据
let averageTemp = []
averageTemp[0] = [72, 75, 79, 79, 81, 81]
averageTemp[1] = [81, 79, 75, 75, 73, 72]
JavaScript 只支持一维数组,并不支持矩阵. 使用数组套数组,实现矩阵或任一多维数组.
// day1
averageTemp[0] = []
averageTemp[0][0] = 72
averageTemp[0][1] = 75
averageTemp[0][2] = 79
averageTemp[0][3] = 79
averageTemp[0][4] = 81
averageTemp[0][5] = 81
// day2
averageTemp[1] = []
averageTemp[1][0] = 81
averageTemp[1][1] = 79
averageTemp[1][2] = 75
averageTemp[1][3] = 75
averageTemp[1][4] = 73
averageTemp[1][5] = 72
迭代二维数组的元素
查看矩阵输出,创建一个通用函数,专门输出其中的值
function printMatrix(myMatrix) {
for (let i = 0; i < myMatrix.length; i++) {
for (let j = 0; j < myMatrix[i].length; j++) {
console.log(myMatrix[i][j])
}
}
}
遍历所有的行和列,使用一个嵌套的 for 循环来处理, 其中变量 i 为行, 变量 j 为列.
使用以下代码查看矩阵 averageTemp 的输出:
printMatrix(averageTemp)
多维数组
创建一个 3 x 3 x 3 的矩阵,每一格里包含矩阵的i(行), j(列) 和z(深度)之和:
let matrix3x3x3 = []
for (let i = 0; i < 3; i++) {
matrix3x3x3[i] = []
for (let j = 0; j < 3; j++) {
matrix3x3x3[i][j] = []
for (let z = 0; z < 3; z++) {
matrix3x3x3[i][j][z] = i+j+z
}
}
}
console.log('matrix3x3x3')
console.log(matrix3x3x3)
for (let i = 0; i < matrix3x3x3.length; i++) {
for (let j = 0; j < matrix3x3x3[i].length; j++) {
for (let z = 0; z < matrix3x3x3[i][j].length; z++) {
console.log(matrix3x3x3[i][j][z])
}
}
}
数组合并 concat
let zero = 0
let positiveNumbers = [1, 2, 3]
let negativeNumbers = [-3, -2, -1]
let numbers = negativeNumbers.concat(zero, positiveNumbers)
console.log(numbers) // [ -3, -2, -1, 0, 1, 2, 3 ]
迭代器函数
let isEven = function (x) {
// 如果x是2的倍数,就返回true
console.log(x)
return (x % 2 == 0)
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
console.log('numbers')
console.log(numbers)
every
迭代数组中的每个元素,直到返回 false
numbers.every(isEven) // 1
some
迭代数组的每个元素,直到函数返回 true
numbers.some(isEven) // 2
forEach
迭代整个数组
numbers.forEach(function (x) {
console.log((x % 2 == 0))
})
// false
// true
// false
// true
// false
// true
// false
// true
// false
// true
// false
// true
// false
// true
// false
map 和 filter 返回新的数组
map
保存了传入 map 方法的 isEven 函数的运行结果
let myMap = numbers.map(isEven)
console.log(myMap)
// [ false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false ]
filter
返回新数组由使用函数返回true的元素组成
let evenNumbers = numbers.filter(isEven)
console.log(evenNumbers)
// [ 2, 4, 6, 8, 10, 12, 14 ]
reduce 方法接收一个函数作为参数, 这个函数有四个参数: previousValue, currentValue, index 和 array. 这个函数会返回一个将被叠加到累加器的值, reduce 方法停止执行后会返回这个累加器. 如果对一个数组中的所有元素求和, 这就很有用, 比如:
let result = numbers.reduce(function (previous, current, index) {
console.log(previous, current, index)
return previous + current
})
console.log(result)
// 1 2 1
// 3 3 2
// 6 4 3
// 10 5 4
// 15 6 5
// 21 7 6
// 28 8 7
// 36 9 8
// 45 10 9
// 55 11 10
// 66 12 11
// 78 13 12
// 91 14 13
// 105 15 14
// 120
forEach 和 箭头函数
numbers.forEach(function (x) {
console.log((x % 2 == 0))
})
numbers.forEach(x => {
console.log((x % 2 == 0))
})
for...of
for (let n of numbers) {
console.log((n % 2 == 0) ? 'even' : 'odd')
}
ES6 新的迭代器(@@iterator)
@@iterator 返回一个包含数组键值对的迭代器对象, 可以通过同步调用得到数组元素的键值对.
ES6 为Array 类增加了一个@@iterator属性,需要通过 Symbol.iterator 来访问. 代码如下:
let iterator = numbers[Symbol.iterator]()
console.log(iterator.next().value)
console.log(iterator.next().value)
console.log(iterator.next().value)
console.log(iterator.next().value)
不断调用迭代器的next方法,就能依次得到数组中的值.numbers数组中有15个值,因此需要调用15次iterator.next().value.
数组中所有值都迭代完后, iterator.next().value 会返回 undefined.
数组的 entries, keys 和 values 方法
entries 方法返回包含键值对的 @@iterator
let aEntries = numbers.entries() // 得到键值对的迭代器
console.log(aEntries) // Object [Array Iterator] {}
console.log(aEntries.next().value) // [0, 1] - 位置0的值为1
console.log(aEntries.next().value) // [1, 2] - 位置1的值为2
console.log(aEntries.next().value) // [2, 3] - 位置2的值为3
numbers 数组中都是数字, key 是数组中的位置, value 是保存在数组索引的值.
keys 方法返回包含数组索引的 @@iterator
let aKeys = numbers.keys()
console.log(aKeys) // Object [Array Iterator] {}
console.log(aKeys.next()) // { value: 0, done: false }
console.log(aKeys.next()) // { value: 1, done: false }
console.log(aKeys.next()) // { value: 2, done: false }
keys方法返回numbers数组的索引. 一旦没有可迭代的值, aKeys.next()就会返回一个value属性为 undefined, done 属性为 true 的对象. 如果 done 属性的值为 false, 就意味着还有可迭代的值.
values 方法返回的 @@iterator 则包含数组的值.
let aValue = numbers.values()
console.log(aValue) // Object [Array Iterator] {}
console.log(aValue.next()) // { value: 1, done: false }
console.log(aValue.next()) // { value: 2, done: false }
console.log(aValue.next()) // { value: 3, done: false }
Array.from
Array.from 方法根据已有的数组创建一个新数组.
let numbers2 = Array.from(numbers)
console.log(numbers2) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
let evens = Array.from(numbers, x => (x % 2 == 0))
console.log(evens)
// [ false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false,
// true,
// false ]
Array.of
Array.of 方法根据传入的参数创建一个新数组
let numbers3 = Array.of(1)
let numbers4 = Array.of(1, 2, 3, 4, 5, 9)
console.log(numbers3) // [ 1 ]
console.log(numbers4) // [ 1, 2, 3, 4, 5, 9 ]
let numbersCopy = Array.of(...numbers4)
console.log(numbersCopy) // [ 1, 2, 3, 4, 5, 9 ]
Array.fill
fill 方法用静态值填充数组
let numbersCopy = Array.of(1, 2, 3, 4, 5, 6)
console.log(numbersCopy) // [ 1, 2, 3, 4, 5, 6 ]
所有位置值都变成了 0
numbersCopy.fill(0)
console.log(numbersCopy) // [ 0, 0, 0, 0, 0, 0 ]
指定开始填充的索引
numbersCopy.fill(2, 1)
console.log(numbersCopy) // [ 0, 2, 2, 2, 2, 2 ]
指定结束填充的索引, 把1填充到数组索引3到5的位置(不包括5)
numbersCopy.fill(1, 3, 5)
console.log(numbersCopy) // [ 0, 2, 2, 1, 1, 2 ]
创建数组并初始化值, 可以使用 fill
let ones = Array(6).fill(1)
console.log(ones) // [ 1, 1, 1, 1, 1, 1 ]
copyWithin
copyWithin
方法复制数组中的一系列元素到同一数组指定的起始位置
把4,5,6三个值复制到数组前三个位置, 得到[4,5,6,4,5,6]这个数组,使用如下代码
let copyArray = [1, 2, 3, 4, 5, 6]
copyArray.copyWithin(0, 3)
console.log(copyArray) // [ 4, 5, 6, 4, 5, 6 ]
把4, 5两个值 (位置3和4) 复制到位置1和2
let copyArray = [1, 2, 3, 4, 5, 6]
copyArray.copyWithin(1, 3, 5)
console.log(copyArray) // [ 1, 4, 5, 4, 5, 6 ]
排序元素
reverse
如原来数组为 [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] , 反序输出数组, 使用 reverse
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
console.log(numbers.reverse()) // [ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
console.log(numbers) // [ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
sort 排序, 把元素默认成字符串进行相互比较
console.log(numbers.sort()) // [ 1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9 ]
sort 升序排列
let numbers = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 8]
console.log(numbers.sort((a, b) => {
return a - b
})) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
这段代码, 在b大于a的时候,返回负数, 反之则返回正数. 如果相等的话,就返回0. 也就是说返回的是负数, 就说明a比b小, 这样 sort 就根据返回值的情况给数组排序.
也可以表示成这样, 会更清晰一点
let numbers = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 8]
function compare(a, b) {
if (a < b) {
return -1
}
if (a > b) {
return 1
}
// a 必须等于 b
return 0
}
console.log(numbers.sort(compare)) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
数组倒序
// reverse order
function compare(a, b) {
if (a < b) {
return 1
}
if (a > b) {
return -1
}
// a 必须等于 b
return 0
}
console.log(numbers.sort(compare)) // [ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
自定义排序
可以对任何对象类型的数组排序, 也可以创建 compareFunction 来比较元素. 例如, 对象 Person 有名字和年龄属性, 根据年龄排序, 可以这么写:
let friends = [
{name: 'John', age: 40},
{name: 'Ana', age: 20},
{name: 'Chris', age: 25}
]
function comparePerson(a, b) {
if (a.age < b.age) {
return -1
}
if (a.age > b.age) {
return 1
}
return 0
}
console.log(friends.sort(comparePerson))
// [ { name: 'Ana', age: 20 },
// { name: 'Chris', age: 25 },
// { name: 'John', age: 40 } ]
字符串排序
let names = ['Ana', 'ana', 'john', 'John']
console.log(names.sort()) // [ 'Ana', 'John', 'ana', 'john' ]
JavaScript 坐字符比较的时候, 是根据字符对应的 ASCII 值来比较的. 例如, A, J, a, j 对应的 ASCII 值分别是 65, 75, 97, 106.
给 sort 传入一个忽略大小写的比较函数, 将会输出 ["Ana", "ana", "John", "john"]:
let names = ['Ana', 'ana', 'john', 'John']
console.log(names.sort((a, b) => {
if (a.toLowerCase() < b.toLowerCase()) {
return -1
}
if (a.toLowerCase() < b.toLowerCase()) {
return 1
}
return 0
})) // ["Ana", "ana", "John", "john"]
搜索
indexOf 方法返回与参数匹配的第一个元素的索引, lastIndexOf 返回与参数匹配的最后一个元素的索引.
let numbers = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 8]
console.log(numbers.indexOf(10)) // 8
console.log(numbers.indexOf(100)) // -1
numbers.push(10)
console.log(numbers.lastIndexOf(10)) //15
console.log(numbers.lastIndexOf(100)) // -1
find 和 findIndex 方法接受一个回调函数, 搜索一个满足回调函数条件的值.find 和 findIndex 的不同之处在于, find 方法返回第一个满足条件的值, findIndex 方法则返回这个值在数组里的索引. 如果没有满足条件的值, find 会返回 undefined , 而 findIndex 返回 -1.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
function multipleOf13(element, index, array) {
return (element % 13 == 0) ? true : false
}
console.log(numbers.find(multipleOf13)) // 13
console.log(numbers.findIndex(multipleOf13)) // 12
includes 方法判断数组中这是否存在某个元素, 如果存在返回 true, 否则返回 false.
console.log(numbers.includes(10)) // true
console.log(numbers.includes(20)) // false
如果给 includes 方法传入一个起始索引, 搜索会从索引指定位置开始:
let numbers2 = [7, 6, 5, 4, 3, 2, 1]
console.log(numbers2.includes(4, 5)) // false
console.log(numbers2.includes(4, 2)) // true
输出数组为字符串
toString 方法把数组中的所有元素输出为一个字符串
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
console.log(numbers) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
console.log(numbers.toString()) // 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
join 方案可以用一个不同的分隔符(比如 -)把元素隔开
let numbersString = numbers.join('-')
console.log(numbersString) // 1-2-3-4-5-6-7-8-9-10-11-12-13-14-15
类型数组
与 C 和 Java 等其他语言不同, JavaScript 数组不是强类型的, 因此它可以存储任意类型的数据.
而类型数组则用于存储单一类型的数据, 它的语法是 let myArray = new TypedArray(length), 其中 TypedArray 需替换为 ( Int8Array
, Uint8Array
, Uint8ClampedArray
, Int16Array
) 等
代码示例如下:
let length = 5
let int16 = new Int16Array(length)
let array16 = []
array16.length = length
for (let i = 0; i < length; i++) {
int16[i] = i + 1
}
console.log(int16) // Int16Array [ 1, 2, 3, 4, 5 ]
node v11.10.0
npm v6.7.0