说明
作用
1、方便保存相似的数据
2、方便遍历这些数据
创建
var a = [];
//和java不一样,没那么严格,可以不同数据类型
//但建议保存相同数据类型的数据,保存多个不同类型的,用对象
//真实开发,是把多个对象放一个数组里面
var b = [1,"2",3,4,true];
var c = new Array(1,3,true,"4");
浏览器中显示:
嵌套:
解构赋值
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
ES6 展开运算符创建
创建了一个新数组
因此可以通过这个方式进行数组的浅拷贝
const a = [1,2,3]
const b = [...a] // b = [1,2,3]
a == b;// false
引用
通过数组的索引值/下标index 引用
a[0]; //数组a的第一个元素,也叫索引值,或者下标index
a[1][2]; //多维数组,a第2个元素是个数组,这个数组中的第3个元素
a[-1] //undefined,不支持负数
数组长度
给数组的长度属性赋值,会改变数组
var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]
不建议下标越界:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
简单的追加元素方法
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[fruits.length] = "Kiwi"; // 向 fruits 追加 "Kiwi"
数组空位(避免)
由于行为不一致和存在性能隐患,因此实践中要避免使用数组空位。
如果确实需要空位,则可以显式地用 undefined 值代替
const options = [,,,,,]; // 创建包含 5 个元素的数组
console.log(options.length); // 5
console.log(options); // [,,,,,]
=================
定型数组
定型数组(typed array)是 ECMAScript 新增的结构,目的是提升向原生库传输数据的效率。
1、有符号的8位整数(int8)
2、无符号的8位整数(uint8)
3、有符号的16位整数(int16)
4、无符号的16位整数(uint16)
5、有符号的32位整数(int32)
6、有符号的32位整数(uint32)
7、32位浮点数(float32)
8、64位浮点数(float64)
// 创建一个7个元素的无符号的定型数组,每个元素都是8位的,也就是每个元素最高不超过2**8=256
const typedArray1 = new Uint8Array(7);
typedArray1[0] = 32;
// Uint8Array [32, 0, 0, 0, 0, 0, 0]
typedArray1[1] = 256;
// Uint8Array [32, 0, 0, 0, 0, 0, 0]
typedArray1[2] = 257;
// Uint8Array [32, 0, 1, 0, 0, 0, 0]
ArrayBuffer
在使用定型数组之前,需要为其分配内存空间,这个内存空间就叫数组缓冲区;一经创建就不能再调整大小。
const buf = new ArrayBuffer(16); // 在内存中分配 16 字节
alert(buf.byteLength); // 16
DataView
通过视图来操作数组缓冲区,包括读取和写入
const buff1= new ArrayBuffer(10);
// 创建视图
const view1= new DataView(buff1);
// 构造函数接收一个可选的字节偏移量和字节长度
// byteOffset=0 表示视图从缓冲起点开始
// byteLength=8 限制视图为前 8 个字节
const firstHalfDataView = new DataVi
const firstHalfDataView = new DataView(buf, 0, 8);
操作
// 创建长度为 8 的 int16 数组
const container = new Int16Array(8);
// 把定型数组复制为前 4 个值
// 偏移量默认为索引 0
container.set(Int8Array.of(1, 2, 3, 4));
console.log(container); // [1,2,3,4,0,0,0,0]
// 把普通数组复制为后 4 个值
// 偏移量 4 表示从索引 4 开始插入
container.set([5,6,7,8], 4);
console.log(container); // [1,2,3,4,5,6,7,8]
// 溢出会抛出错误
container.set([5,6,7,8], 7);
// RangeError
const source = Int16Array.of(2, 4, 6, 8);
// 把整个数组复制为一个同类型的新数组
const fullCopy = source.subarray();
console.log(fullCopy); // [2, 4, 6, 8]
// 从索引 2 开始复制数组
const halfCopy = source.subarray(2);
console.log(halfCopy); // [6, 8]
// 从索引 1 开始复制到索引 3
const partialCopy = source.subarray(1, 3);
console.log(partialCopy); // [4, 6]
=================
数组方法
https://www.runoob.com/jsref/jsref-obj-array.html
把数组转换为字符串
toString( ) 把数组转换为数组值(逗号分隔)的字符串
join( “符号”) 所有数组元素,通过特定的符号分隔,结合为一个字符串
添加元素
unshift( 元素值 ) (在开头)向数组添加新元素,返回新数组长度
push( 元素值 ) (结尾处)向数组添加新的元素,返回新数组长度
push( …数组名 ) (结尾处)向数组添加其他数据的所有元素,返回新数组长度
数组[ 数组.length ] = 元素值 (结尾处)向数组添加新的元素
splice(新元素的位置); 从特定位置,删除后面所有元素,并返回一个包含已删除项的数组
splice( 新元素的位置 , 应删除多少元素 , 新元素1 , 新元素2 , … ,新元素n) 方法可用于向数组添加新项,返回一个包含已删除项的数组
数组1.concat( 数组2 , 数组3 ) 通过合并(连接)现有数组来创建返回一个新数组,数组2会在后面,数组3在最后面
Array.of(1, 2, 3, 4); // [1, 2, 3, 4]
删除元素 / 提取
shift( ) 删除首个数组元素,返回被删除的值
pop( ) 删除最后一个元素,返回被删除的值
delete 数组[下标]; 删除指定下标的元素,但是会留下未定义的空间
splice(新元素的位置 , 应删除多少元素); 从特定位置,删除多少个元素,返回一个包含已删除项的数组
splice(0) 清空数组
更改元素
数组[下标] = 新元素值
splice(新元素的位置 , 应删除多少元素); 从特定位置,选择多少个元素,返回一个新的数组
查找
indexOf(元素值); 返回元素值首次出现的位置下标,不存在就是-1
lastIndexOf(元素值); 返回元素值最后一次出现的位置下标
使用的都是全等(===)比较
是否包含某个元素
indexOf(元素值); 返回元素值首次出现的位置下标,不存在就是-1(无法判断NaN)
includes(元素值);是否有某个元素,有就是true,ES7新增(可以判断NaN)
条件查找
断言函数接收 3 个参数:元素、索引和数组本身。
其中元素是数组中当前搜索的元素,
索引是当前元素的索引,
而数组就是正在搜索的数组。
断言函数返回真值,表示是否匹配。
const people = [
{
name: "Matt",
age: 27
},
{
name: "Nicholas",
age: 29
}
];
alert(people.find((element, index, array) => element.age < 28));
// {name: "Matt", age: 27}
alert(people.findIndex((element, index, array) => element.age < 28));
// 0
找到匹配项后,这两个方法都不再继续搜索。
遍历(迭代)
访问一遍数组的各个元素
var a = ['A', 'B', 'C'];
//方法1:for循环
for(i=0 ; i < a.length ; i++){
console.log(i + ', index = ' ,a[i]);
}
//方法2:for in 循环
for(i in a){
console.log(a[i]); //下标 in 数组
}
//方法3:for of循环
for(i of a){
console.log(i); //元素 of 数组
}
//方法4:数组内置的方法,没有返回值
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
console.log(element + ', index = ' + index);
});
检查元素
every:如果对每一项函数都返回 true,则这个方法返回 true。
some:如果有一项函数返回 true,则这个方法返回 true
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let everyResult = numbers.every((item, index, array) => item > 2);
alert(everyResult); // false
let someResult = numbers.some((item, index, array) => item > 2);
alert(someResult); // true
处理所有元素
和forEach()方法很像,但是forEach()方法没有返回值,map有返回值
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let mapResult = numbers.map((item, index, array) => item * 2);
alert(mapResult); // 2,4,6,8,10,8,6,4,2
fill 填充
const zeroes = [0, 0, 0, 0, 0];
// 用 5 填充整个数组
zeroes.fill(5);
console.log(zeroes); // [5, 5, 5, 5, 5]
zeroes.fill(0); // 重置
// 用 6 填充索引大于等于 3 的元素
zeroes.fill(6, 3);
console.log(zeroes); // [0, 0, 0, 6, 6]
// 用 7 填充索引大于等于 1 且小于 3 的元素
zeroes.fill(7, 1, 3);
console.log(zeroes); // [0, 7, 7, 0, 0];
// 用 8 填充索引大于等于 1 且小于 4 的元素
// (-4 + zeroes.length = 1)
// (-1 + zeroes.length = 4)
zeroes.fill(8, -4, -1);
console.log(zeroes); // [0, 8, 8, 8, 0];
//fill()静默忽略超出数组边界、零长度及方向相反的索引范围:
const zeroes = [0, 0, 0, 0, 0];
// 索引过低,忽略
zeroes.fill(1, -10, -6);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引过高,忽略
zeroes.fill(1, 10, 15);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引反向,忽略
zeroes.fill(2, 4, 2);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引部分可用,填充可用部分
zeroes.fill(4, 3, 10)
console.log(zeroes); // [0, 0, 0, 4, 4]
copyWithin 复制
ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
ints.copyWithin(5); // 从 ints 中复制索引 0 开始的内容,插入到索引 5 开始的位置,在源索引或目标索引到达数组边界时停止
console.log(ints); // [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
ints.copyWithin(0, 5);
console.log(ints); // [5, 6, 7, 8, 9, 5, 6, 7, 8, 9] // 从 ints 中复制索引 5 开始的内容,插入到索引 0 开始的位置
// 从 ints 中复制索引 0 开始到索引 3 结束的内容
// 插入到索引 4 开始的位置
ints.copyWithin(4, 0, 3);
alert(ints); // [0, 1, 2, 3, 0, 1, 2, 7, 8, 9]
// JavaScript 引擎在插值前会完整复制范围内的值
// 因此复制期间不存在重写的风险
ints.copyWithin(2, 0, 6);
alert(ints); // [0, 1, 0, 1, 2, 3, 4, 5, 8, 9]
// 支持负索引值,与 fill()相对于数组末尾计算正向索引的过程是一样的
ints.copyWithin(-4, -7, -3);
alert(ints); // [0, 1, 2, 3, 4, 5, 3, 4, 5, 6]
copyWithin()静默忽略超出数组边界、零长度及方向相反的索引范围:
let ints,
reset = () => ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 索引过低,忽略
ints.copyWithin(1, -15, -12);
alert(ints); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 索引过高,忽略
ints.copyWithin(1, 12, 15);
alert(ints); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 索引反向,忽略
ints.copyWithin(2, 4, 2);
alert(ints); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 索引部分可用,复制、填充可用部分
ints.copyWithin(4, 7, 10)
alert(ints); // [0, 1, 2, 3, 7, 8, 9, 7, 8, 9];
浅复制(浅拷贝)
// Array.from()对现有数组执行浅复制
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1);
alert(a1 === a2); // false
截取
var names = ["abc", "cba", "nba", "dna"]
var newNames1 = names.slice(0, 2) // 原始数组不会被改变
console.log(newNames1) // ["abc", "cba", "nba"]
console.log(names) // ["abc", "cba", "nba", "dna"]
数字排序
1、sort方法排序
reverse是相反的sort
var points = [40, 100, 1, 5, 25, 10];
points.sort(); //[1, 10, 100, 25, 40, 5] 按字符串来排序
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
points.sort(compare);
//1,5,10,25,40,100
//当 sort() 函数比较两个值时,会将值发送到比较函数,
//并根据所返回的值(负、零或正值)对这些值进行排序。
points.sort((a, b) => a < b ? 1 : a > b ? -1 : 0); //箭头函数简写
points.sort((a, b) => a-b); //箭头函数简写
2、冒泡排序
3、选择排序
用第一个元素,和后面每个元素进行比较。
再用第二个元素,和后面每个元素进行比较。
再用第三个元素,和每个元素进行比较。
…..
排序对象数组
var cars = [
{type:"Volvo", year:2016},
{type:"Saab", year:2001},
{type:"BMW", year:2010}];
//数字排序
cars.sort(function(a, b){return a.year - b.year});
//字母排序
cars.sort(function(a, b){
var x = a.type.toLowerCase();
var y = b.type.toLowerCase();
if (x < y) {return -1;}
if (x > y) {return 1;}
return 0;
});
反向排序 reverse
let values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); // 5,4,3,2,1
最大最小值
sort();方法排序后,可以得到首尾的最大最小值,但是效率不高。
可以用数据Math的方法
var x = Math.max.apply(null,array);
var x = Math.min.apply(null,array);
filter 过滤函数
Array.from 遍历处理函数
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1, x => x**2);
const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2});
console.log(a2); // [1, 4, 9, 16]
console.log(a3); // [1, 4, 9, 16]
map 遍历处理函数
reduce 遍历汇总函数
reduceRight() 从右边开始
let values = [1, 2, 3, 4, 5];
// 上一个归并值、当前项、当前项的索引和数组本身
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15
from 拆分、转换
// 字符串会被拆分为单字符数组
console.log(Array.from("Matt")); // ["M", "a", "t", "t"]
// 可以使用 from()将集合和映射转换为一个新数组
const m = new Map().set(1, 2)
.set(3, 4);
const s = new Set().add(1)
.add(2)
.add(3)
.add(4);
console.log(Array.from(m)); // [[1, 2], [3, 4]]
console.log(Array.from(s)); // [1, 2, 3, 4]
// Array.from()对现有数组执行浅复制
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1);
console.log(a1); // [1, 2, 3, 4]
alert(a1 === a2); // false
// arguments 对象可以被轻松地转换为数组
function getArgsArray() {
return Array.from(arguments);
}
console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3, 4]
// from()也能转换带有必要属性的自定义对象
const arrayLikeObject = {
0: 1,
1: 2,
2: 3,
3: 4,
length: 4
};
console.log(Array.from(arrayLikeObject)); // [1, 2, 3, 4]
//新数组批量变化
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1, x => x**2);
const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2});
console.log(a2); // [1, 4, 9, 16]
console.log(a3); // [1, 4, 9, 16]
ES10 降低维度
把多维数组降低维度,默认是降低1个维度(就是解掉一个中括号[ ])
遍历再降维