创建和初始化数组
数组是最简单的内存数据结构。
Q:为什么用数组?
A:
使用 new 关键字创建和初始化数组(不推荐)
- 使用
new关键字声明并初始化 - 可以创建一个指定长度的数组
- 可以直接将数组元素作为参数传递给它的构造器
let week = new Array();week = new Array(7);week = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
使用 [] 的形式创建和初始化数组(推荐)
let week = [];// orweek = ['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(); // -3console.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、4numbers.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); // 1console.log(myIterator.next()); // { value: 2, done: false }console.log(myIterator.next().value); // 2console.log(myIterator.next().value); // 3console.log(myIterator.next().value); // 4console.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)); // 9console.log(numbers.indexOf(100)); // -1console.log(numbers.lastIndexOf(10)); // 13console.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)); // 3console.log(numbers.findIndex(multipleOf3)); // 2
数组元素搜索 includes()
includes() 方法(如果数组里存在某个元素,includes() 方法会返回 true,否子返回 false)
console.log(numbers.includes(15)); // trueconsole.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,15console.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]*/
