创建和初始化数组
数组是最简单的内存数据结构。
Q:为什么用数组?
A:
使用 new
关键字创建和初始化数组(不推荐)
- 使用
new
关键字声明并初始化 - 可以创建一个指定长度的数组
- 可以直接将数组元素作为参数传递给它的构造器
let week = new Array();
week = new Array(7);
week = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
使用 []
的形式创建和初始化数组(推荐)
let week = [];
// or
week = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
- 使用数组的
length
属性输出数组存了多少个元素(它的大小)
console.log(week.length); // 7
- 访问元素和迭代数组
for (let i = 0; i < week.length; i++) {
console.log(week[i]);
}
// 输出每个元素后都是换行的,这里用两个空格代表,你懂的
// Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Example:斐波那契数列
斐波那契数列中的前两项是 1,从第三项开始,每一项都等于前两项之和。
// 求斐波那契数列的前 20 个数
let a = 20;
const fibonacci = [];
fibonacci[1] = 1;
fibonacci[2] = 1;
for(let i = 3; i < a; i++) {
fibonacci[i] = fibonacci[i -1] + fibonacci[i -2];
}
for(let i = 1; i < fibonacci.length; i++) {
console.log(fibonacci[i]);
}
// 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
添加元素
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
在数组末尾插入元素
- 把值赋给数组中最后一个空位上的元素
numbers[numbers.length] = 10;
push()
方法(在数组的末尾添加元素)
numbers.push(11);
numbers.push(12, 13);
console.log(numbers); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
在数组开头插入元素
- (原生)在数组开头插入元素
Array.prototype.insertFirstPosition = function (value) {
for (let i = this.length; i >= 0; i--) {
this[i] = this[i - 1];
}
this[0] = value;
}
numbers.insertFirstPosition(-1); // [ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
unshift()
(在数组的开头添加元素)
numbers.unshift(-2);
numbers.unshift(-4, -3);
console.log(numbers); // [ -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
删除元素
在数组末尾删除元素
pop()
(从数组末尾删除元素)
numbers.pop();
console.log(numbers); // [ -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
在数组开头删除元素
- (原生)从数组开头删除元素(不推荐)
// 步骤一:将所有不是 undefined 的值从原来的数组复制到新的数组中,创建一个 reIndex 方法
Array.prototype.reIndex = function(myArray) {
const newArray = [];
for (let i = 0; i < myArray.length; i++) {
if (myArray[i] !== undefined) {
newArray.push(myArray[i]);
}
}
return newArray;
}
// 步骤二:手动移除第一个元素并重新排序
Array.prototype.removeFirst = function() {
for (let i = 0; i < this.length; i++) {
this[i] = this[i + 1];
}
return this.reIndex(this);
};
// 步骤三:调用函数删除
numbers.removeFirst();
console.log(numbers); // [ -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, undefined ]
从中可以得出,只是用后一个值覆盖了前一个值,数组长度并未改变。
shift()
(删除数组的第一个元素)
shift()
方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
numbers.shift(); // -3
console.log(numbers); // [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, undefined ]
在数组任意位置添加或删除元素 splice()
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
参数:
- 第一个:表示想要删除或插入的元素的索引值
- 第二个:表示想要删除元素的个数
- 第三个往后:表示想要添加到数组里的值
// 删除从数组索引 5 开始的 3 个元素
numbers.splice(5, 3); // [ 3, 4, 5 ]
// 从索引 5 开始添加元素 2、3、4
numbers.splice(5, 0, 2, 3, 4); // []
console.log(numbers); // [-2, -1, 0, 1, 2, 2, 3, 4, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, undefined]
二维和多维数组
Q:为什么用二维数组(矩阵)?
A:
- 二维数组
迭代所有的行和列,使用一个嵌套的 for 循环来处理,其中变量 i 为行,变量 j 为列。在这种情况下,每个 myMatrix[i] 同样代表一个数组,因此需要在嵌套的 for 循环中迭代 myMatrix[i] 的每个位置。
// 二维数组
let matrix = [];
matrix[0] = [72, 75, 79, 79, 81, 81];
matrix[1] = [81, 79, 75, 75, 73, 73];
// 迭代二维数组的元素
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]);
}
}
}
printMatrix(matrix);
// 输出每个元素后都是换行的,这里用两个空格代表,你懂的(下面的也是这样)
// 72 75 79 79 81 81
// 81 79 75 75 73 73
- 多维数组
// 多维数组(例如:创建一个 3*3*3 的矩阵,每一个格子里包含矩阵的 i(行)、j(列)、z(深度) 之和)
const matrix3 = [];
for (let i = 0; i < 3; i++) {
matrix3[i] = []; // 初始化每个数组
for (let j = 0; j < 3; j++) {
matrix3[i][j] = [];
for (let z = 0; z < 3; z++) {
matrix3[i][j][z] = i + j + z;
}
}
}
// 迭代多维数组
for (let i = 0; i < matrix3.length; i++) {
for (let j = 0; j < matrix3[i].length; j++) {
for (let z = 0; z < matrix3[i][j].length; z++) {
console.log(matrix3[i][j][z]);
}
}
}
// 0 1 2 1 2 3 2 3 4
// 1 2 3 2 3 4 3 4 5
// 2 3 4 3 4 5 4 5 6
数组合并 concat()
concat()
连接 2 个或 2 个已上的数组,并返回结果。concat()
可以向一个数组传递数组、对象或是元素。数组会按照该方法传入的参数顺序连接指定的数组。
const zero = 0;
const positiveNumbers = [1, 2, 3];
const negativeNumbers = [-3, -2, -1];
let numbers = negativeNumbers.concat(zero, positiveNumbers); // [-3, -2, -1, 0, 1, 2, 3]
迭代数组元素
我们需要一个数组和一个函数:如果数组里的元素可以被 2 整除(偶数),函数就返回 true,否则返回 false。
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const isEven = x => x % 2 === 0;
/* 另一种实现方式
function isEven(x) {
// return x % 2 === 0 ? true : false;
return (x % 2 === 0);
}
*/
迭代器 every()
用 every()
方法迭代(every()
方法会迭代数组中的每一个元素,直到返回 false
)
const myEvery = numbers.every(isEven);
console.log(myEvery); // false
迭代器 some()
用 some()
方法迭代(some()
方法会迭代数组中的每一个元素,直到返回 true
)
const mySome = numbers.some(isEven);
console.log(mySome); // true
迭代器 forEach()
用 forEach()
方法迭代(forEach()
方法会迭代数组中的每一个元素,它和使用 for
循环的结构相同)
numbers.forEach(x => console.log(x % 2 === 0));
// false true false true false true false true false true false true false true false
迭代器 map()
用 map()
方法迭代(map()
方法会返回新数组)
const myMap = numbers.map(isEven);
console.log(myMap); // [ false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]
迭代器 filter()
用 filter()
方法迭代(filter()
方法返回的新数组由 isEven()
函数返回 true
的元素)
const myFilter = numbers.filter(isEven);
console.log(myFilter); // [ 2, 4, 6, 8, 10, 12, 14 ]
迭代器 reduce()
reduce()
方法迭代 (reduce()
方法会返回一个将被叠加到累加器的值,reduce()
方法停止执行后会返回这个累加器)
const myReduce = numbers.reduce((previousValue, currentValue) => previousValue + currentValue);
console.log(myReduce); // 120
迭代器 entries()
使用 entries()
迭代(返回包含数组所有键值对的 @@iterator
)
let myRntries = numbers.entries();
console.log(myRntries.next().value); // [ 0, 1 ]
console.log(myRntries.next().value); // [ 1, 2 ]
console.log(myRntries.next().value); // [ 2, 3 ]
// ...
myRntries = numbers.entries();
for (const n of myRntries) {
console.log(n);
}
// [ 0, 1 ] [ 1, 2 ] [ 2, 3 ] [ 0, 1 ] [ 1, 2 ] [ 2, 3 ] [ 3, 4 ] [ 4, 5 ] [ 5, 6 ]
// [ 6, 7 ] [ 7, 8 ] [ 8, 9 ] [ 9, 10 ] [ 10, 11 ] [ 11, 12 ] [ 12, 13 ] [ 13, 14 ] [ 14, 15 ]
迭代器 keys()
keys()
方法迭代(返回包含数组所有索引的 @@iterator
)
let myKeys = numbers.keys();
console.log(myKeys.next()); // { value: 0, done: false }
console.log(myKeys.next()); // { value: 1, done: false }
console.log(myKeys.next()); // { value: 2, done: false }
// ...
myKeys = numbers.keys();
for (const n of myKeys) {
console.log(n);
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
迭代器 values()
values()
方法迭代(返回包含数组所有值的 @@iterator
)
let myValues = numbers.values();
console.log(myValues.next()); // { value: 1, done: false }
console.log(myValues.next()); // { value: 2, done: false }
console.log(myValues.next()); // { value: 3, done: false }
// ...
myValues = numbers.values();
for (const n of myValues) {
console.log(n);
}
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
@@iterator
使用 @@iterator
(返回一个包含数组键值对的迭代器对象,可以通过同步调用得到数组元素的键值对)
let myIterator = numbers[Symbol.iterator]();
console.log(myIterator.next().value); // 1
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next().value); // 2
console.log(myIterator.next().value); // 3
console.log(myIterator.next().value); // 4
console.log(myIterator.next().value); // 5
// ...
myIterator = numbers[Symbol.iterator]();
for (const n of myIterator) {
console.log(n);
}
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
创建一个新数组 from()
和 Array.of()
创建一个新数组 from()
使用 from()
方法(根据已有数组创建一个新的数组)
let numbers2 = Array.from(numbers); // 复制 numbers 数组
console.log(numbers2);
let evens = Array.from(numbers, x => (x % 2) == 0); // 传入一个用来过滤值得函数)
console.log(evens);
创建一个新数组 Array.of()
使用 Array.of()
方法(根据传入得参数创建一个新数组)
let numbers3 = [1];
let numbers4 = [1, 2, 3, 4, 5,];
let numbersCopy = Array.from(numbers4);
下面 3 行代码等效于上面 3 行代码
- 使用
Array.of()
方法 复制已有的数组 - 展开运算符(
...
)会把numbers4
数组里得值都展开成参数
let numbers3 = Array.of(1);
let numbers4 = Array.of(1, 2, 3, 4, 5,);
let numbersCopy = Array.of(...numbers4);
console.log(numbers3); // [ 1 ]
console.log(numbers4); // [ 1, 2, 3, 4, 5 ]
console.log(numbersCopy); // [ 1, 2, 3, 4, 5 ]
填充数组 fill()
注意:会改变原始数组,所以应特别注意
let fillNumbers = Array.of(1, 2, 3, 4, 5, 6);
所有的都填充为 0
let myFill = fillNumbers.fill(0);
console.log(myFill); // [ 0, 0, 0, 0, 0, 0 ]
指定开始填充得索引,从 1 开始得所有位置都填充为 2
let myFill = fillNumbers.fill(2, 1);
console.log(myFill); // [ 0, 2, 2, 2, 2, 2 ]
指定结束填充的索引,把 1 填充到数组索引 3 到 5 的位置(包括 3 不包括 5)
let myFill = fillNumbers.fill(1, 3, 5);
console.log(myFill); // [ 0, 2, 2, 1, 1, 2 ]
创建数组并初始化值得时候,fill()
方法非常好用
let ones = Array(6).fill(1);
console.log(ones); // [ 1, 1, 1, 1, 1, 1 ]
复制数组元素 copyWithin()
使用 copyWithin()
方法(复制数组中一系列元素到同一数组指定的起始位置)
注意:会改变原始数组,所以应特别注意
let copyArray = [1, 2, 3, 4, 5, 6];
例如:把 4、5、6 三个值复制到数组前三个位置
let myCopyWithin = copyArray.copyWithin(0, 3);
console.log(myCopyWithin); // [ 4, 5, 6, 4, 5, 6 ]
把 从位置 3 开始到位置 5(包括 3 不包括 5)的元素复制到位置 1
let myCopyWithin = copyArray.copyWithin(1, 3, 5);
console.log(myCopyWithin); // [ 4, 4, 5, 4, 5, 6 ]
数组元素排序
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
数组元素排序 reverse()
使用 reverse()
方法(反序输入数组)
let myReverse = numbers.reverse();
console.log(myReverse); // [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
数组元素排序 sort()
- 不传参数直接使用
sort()
方法
sort()
方法在对数组做排序时,把元素默认成字符串进行相互比较
let mySort = numbers.sort();
console.log(mySort); // [1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9]
- 传入自己写的比较函数
mySort = numbers.sort((a, b) => a - b);
console.log(mySort); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
b > a 时,这段代码会返回负数,反之则返回正数,相等就返回 0,这样
sort()
方法就能根据返回值的情况对数组进行排序
另一种实现方式
function compare(a, b) {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
mySort = numbers.sort(compare);
console.log(mySort); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
- 自定义排序 —— 对任何对象类型的数组排序
const friends = [
{ name: 'John', age: 20 },
{ name: 'Charles', age: 22 },
{ name: 'Bruce', age: 18 },
];
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': 'Bruce', 'age': 18 },
{ 'name': 'John', 'age': 20 },
{ 'name': 'Charles', 'age': 22 }
]
*/
- 字符串排序
let names = ['Ana', 'ana', 'john', 'John'];
console.log(names.sort()); // ['Ana', 'John', 'ana', 'john']
忽略大小写进行排序
function compareString(a, b) {
if (a.toLowerCase() < b.toLowerCase()) {
return -1;
}
if (a.toLowerCase() > b.toLowerCase()) {
return 1;
}
return 0;
}
console.log(names.sort(compareString)); // ['Ana', 'ana', 'John', 'john']
按照大小写字母顺序排序,小写排在前面
let mySortString = names.sort((a, b) => a.localeCompare(b));
console.log(mySortString); // ['ana', 'Ana', 'john', 'John']
假如对带有重音符号的字符做排序的话,也可以用 localeCompare 来实现
数组元素搜索
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 10, 15];
数组元素搜索 indexOf()
和 lastIndexOf()
indexOf()
方法(返回与参数匹配的第一个元素的索引,没有匹配上返回 -1)lastIndexOf()
方法(返回与参数匹配的最后一个元素的索引,没有匹配上返回 -1)
console.log(numbers.indexOf(10)); // 9
console.log(numbers.indexOf(100)); // -1
console.log(numbers.lastIndexOf(10)); // 13
console.log(numbers.lastIndexOf(100)); // -1
数组元素搜索 find()
和 findIndex()
- find() 方法(接受一个回调函数,搜索一个满足回调函数条件的值,没有搜索到满足条件的情况下返回
undefined
) findIndex()
方法(接受一个回调函数,搜索一个满足回调函数条件的索引,没有搜索到满足条件的情况下返回 -1)
function multipleOf3(element, index, array) {
return element % 3 == 0;
}
console.log(numbers.find(multipleOf3)); // 3
console.log(numbers.findIndex(multipleOf3)); // 2
数组元素搜索 includes()
includes()
方法(如果数组里存在某个元素,includes()
方法会返回 true
,否子返回 false
)
console.log(numbers.includes(15)); // true
console.log(numbers.includes(20)); // false
// 传入一个起始索引,搜索会从索引指定的位置开始
console.log(numbers.includes(4, 5)); // false(索引 5 之后的元素不包含 4)
输出数组为字符串 toString()
和 join()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 10, 15];
console.log(numbers.toString()); // 1,2,3,4,5,6,7,8,9,10,11,12,13,10,15
console.log(numbers.join('-')); // 1-2-3-4-5-6-7-8-9-10-11-12-13-10-15
类型数组
类型数组 | 数据类型 |
---|---|
Int8Array | 8 位二进制补码整数 |
Uint8Array | 8 位无符号整数 |
Uint8ClampedArray | 8 位无符号整数 |
Int16Array | 16 位二进制补码整数 |
Uint16Array | 16 位无符号整数 |
Int32Array | 32 位二进制补码整数 |
Uint32Array | 32 位无符号整数 |
Float32Array | 32 位IEEE浮点数 |
Float64Array | 64 位IEEE浮点数 |
let length = 50;
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, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50
]
*/