一、基本概念
数组是值的有序集合。
每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。
数组是无类型的。
数组元素可以是任意类型,并且同一个数组中的不同元素也可以有不同的类型。
数组的元素可以是对象或其他数组,从而创建复杂的数据结构。
数组是动态的
根据需要会 增长或缩减,并在创建数组时无须声明一个固定的大小或者在数组大小变化时无须重新分配空间。
数组可以时稀疏的
数组元素的索引不一定要连续,他们之间可以有空缺。
每个JavaScript数组都有一个length属性。针对非稀疏数组,该属性就是元素个数。针对稀疏数组,length比实际元素个数大。
数组是对象的特殊形式
数组索引可以认为是整数的属性名。
数组继承自Array.prototype中的属性
定义了一套丰富的数组操作方法,不仅对真正的数组有效,还对“类数组对象”同样有效。如:字符串、arguments等。
二、操作数组
创建数组
数组字面量
let empty = [];
let primes = [2, 3, 5, 7, 11];
let misc = [1.1, true, "a"];
let base = 10;
let numbers = [base, base + 1, base++, ++base];
let b = [
[1, { x: 1, y: 2 }],
[2, { x: 3, x: 4 }],
];
let count = [1, , 3];
let others = [, ,];
构造函数Array()
let a1 = new Array(); //相当于[]
let a2 = new Array(10);
let a3 = new Array(1, 2, 3, "四", "五", "六");
读写数组元素
使用[ ]操作符来访问数组中的元素
方括号是一个返回非负整数值得任意表达式
该方法既可读又可写。
let a = ["world"];
let value = a[0];
a[1] = 3.14;//3.14
i = 2;
a[i] = 3;//3
a[i + 1] = 4;//4
a[a[i]] = a[0];//"world"
a["10"] = "hi";//"hi"
a["ten"] = "hoo";//"hoo"
a[-2] = -2;//-2
a[1.11] = 1.11;//1.11
稀疏数组
包含从0开始的不连续索引的数组。
可以用Array()构造函数或简单指定数组的索引值大于当前的数组长度来创建稀疏数组。
JavaScript中的数组根本没有索引,因为索引应该是数字,而JavaScript中数组的索引其实是字符串
稀疏也就是说,数组中的元素之间可以有空隙,因为一个数组其实就是一个键值映射。当你遍历它时,你会发现,它并没有元素,JavaScript会跳过这些缝隙。
let a1 = [, , ,];
let a2 = new Array(4);
console.log(1 in a1, 1 in a2);//两个数组中并没有1这个值,所以输出 false,false
a1[10] = 100;
a1[8] = undefined;
for (let a in a1) {
console.log(a, a1[a]);
}
//前索引0-7为undefined,索引8时输出8,undefined,索引9也为undefined,索引10输出10,100
for (let b of a1) {
console.log(b);
}
数组长度
每个数组有一个length属性,代表数组中元素的个数。
设置为一个小于当前长度的非负整数n时,当前数组中那些索引值大于或等于n的元素将从中删除。
设置为大于其当前的长度,会在数组尾部创建一系列空的区域。
可以用 Object.defineProperty() 让数组的length属性变成只读的。
let arr = [1, 2, 3];
arr.length = 5;
console.log(arr);//[ 1, 2, 3, <2 empty items> ]
Object.defineProperty(arr, "length", {
writable: true,//可写的,默认为false
configurable: false,//当且仅当该属性的 configurable 为 true 时,
//该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。
//默认为 false。可见它不仅控制了该属性是否可被删除,而且控制了属性描述符是否能改变。
//为false时除了value和writable能单向从true改为false外,改变其他属性都会报错
});
arr.length = 3;
console.log(arr);//[1,2,3]
arr.push(1000);//添加一个值为1000的数组元素
console.log(arr);//[1,2,3,1000]
数组元素的添加和删除
数组末尾添加
var fruits = ['Apple', 'Banana'];
var newLength = fruits.push('Orange');
console.log(newLength);
console.log(fruits);
//3
//['Apple', 'Banana','Orange']
数组末尾删除
var fruits = ['Apple', 'Banana'];
console.log(fruits);//['Apple', 'Banana']
var last = fruits.pop();
console.log(fruits);//['Apple']
数组头部添加
var fruits = ['Apple', 'Banana'];
console.log(fruits);//[ 'Apple', 'Banana' ]
var newLength = fruits.unshift('Strawberry')
console.log(fruits);//[ 'Strawberry', 'Apple', 'Banana' ]
数组头部删除
var fruits = ['Apple', 'Banana'];
console.log(fruits);//[ 'Apple', 'Banana' ]
var first = fruits.shift();
console.log(fruits);//[ 'Banana' ]
数组遍历
let arr = [1, 2, 3, 4, 5];
console.log(Object.keys(arr));//keys:对键名的遍历
//[ '0', '1', '2', '3', '4' ]
arr.test = "hello";
console.log(Object.keys(arr));//[ '0', '1', '2', '3', '4', 'test' ]
console.log(Object.values(arr));//value:对键值的遍历
//[ 1, 2, 3, 4, 5, 'hello' ]
console.log(Object.entries(arr));//entries:对键值对的遍历
//[
//[ '0', 1 ],
//[ '1', 2 ],
//[ '2', 3 ],
//[ '3', 4 ],
//[ '4', 5 ],
//[ 'test', 'hello' ]
//]
//for...in,for...in 语句以原始插入顺序迭代对象的可枚举属性。
for (let k in arr) {
console.log(k, arr[k]);
}
//0 1
//1 2
//2 3
//3 4
//4 5
//test hello
arr[8] = 9;
for (let k in arr) {
console.log(k, arr[k]);
}
//0 1
//1 2
//2 3
//3 4
//4 5
//8 9
//test hello
//for...of(ES6),for...of 语句遍历可迭代对象定义要迭代的数据。
for (let d of arr) {
console.log(d);
}
//1
//2
//3
//4
//5
//undefined
//undefined
//undefined
//9
arr[7] = undefined;
//for循环
for (let i = 0; i < arr.length; i++) {
if (i in arr) console.log(arr[i]);
}
//1
//2
//3
//4
//5
//undefined
//9
三、数组方法
实例方法
join():将数组中所有元素都转化为字符串连接在一起,返回最后生成的字符串。
可以指定一个可选的字符串在生成的字符串中来分隔数组的各个元素。如果不指定分隔符,默认使用逗号。
let arr = [1,2,3,4,5];
console.log(arr.join("-"), arr.join());
//1-2-3-4-5 1,2,3,4,5
reverse():将数组中的元素颠倒顺序,返回逆序的数组。
let arr = [1,2,3,4,5]
let r_arr = arr.reverse();
console.log(r_arr, arr);
//[ 5, 4, 3, 2, 1 ] [ 5, 4, 3, 2, 1 ]
sort():将数组中的元素排序并返回排序后的数组。
当不带参数调用sort()时,数组元素以字母表顺序排序(如有必要将临时转化为字符串进行比较)。
let data = [22, 4, 111, 30];
let sdata = data.sort();
console.log(data, sdata);
//[ 111, 22, 30, 4 ] [ 111, 22, 30, 4 ]
给sort()方法传递一个比较函数。该函数决定了它的两个参数在排好序的数组中的先后顺序。
sdata = data.sort(function (a, b) {
return a - b;
});
console.log(sdata);
//[ 4, 22, 30, 111 ]
concat():创建并返回一个新的数组,他的元素包括调用concat()的原始数组的元素和concat()的每一参数
let arr = [1, 2, 3, 4, 5];
let a1 = arr.concat(10, 20);
let a2 = arr.concat([10, 20]);
let a3 = arr.concat([10, 20], [30, 40]);
let a4 = arr.concat([10, [20, 30]]);
console.log(a1);//[1,2,3,4,5,10,20]
console.log(a2);//[1,2,3,4,5,10,20]
console.log(a3);//[1, 2, 3, 4, 5,10, 20, 30, 40]
console.log(a4);//[1,2,3,4,5,10,[20,30]]
console.log([...arr, 10, 20]);//[1,2,3,4,5,6,10,20]
slice():返回指定数值的一个片段或子数组。两个参数分别指定了片段的开始和结束位置,包括开头,不包括结尾。
let sub_arr = arr.slice(3, 8);
console.log(sub_arr);//[4,5,6,7,8]
sub_arr = arr.slice(1, -1);
console.log(sub_arr);//[2,3,4,5,6,7,8,9] 负数为从后往前数
splice():在数组中插入或删除元素的通用方法。不同于slice()和concat(),splice()会修改调用的数组。
参数index:整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany:要删除的项目数。如果为零就相当于不删除。
item1,…,itemX:要添加的新元素。
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"
console.log(arr);
//George,John,Thomas,James,Adrew,Martin
arr.splice(2,0,"William")
console.log(arr);
//George,John,William,Thomas,James,Adrew,Martin
arr.splice(2,1,"William")
console.log(arr);
//George,John,William,James,Adrew,Martin
arr.splice(2,3,"William")
console.log(arr);
//George,John,William,James,Adrew,Martin
push( )和pop( )
允许将数组当做栈来使用。
push()方法在数组的尾部添加一个或多个元素,并返回数组新的长度。
pop()方法为删除数组的最后一个元素,减小数组长度并返回它删除的值。
注意,两个方法都修改并替换原始数组而非生成一个修改版的新数组。
unshift()和shift()
unshift()在数组的头部添加一个或多个元素,并将已存在的元素移动到更高索引的位置来获得足够的空间,最后返回数组新的长度。
shift()删除数组的第一个元素并将其返回,然后把所有随后的元素上移一个位置来填补数组头部的空缺。
ES5:遍历、映射、过滤、检测
简化和搜索数组
forEach()方法从头至尾遍历数组,为每个元素调用指定的函数。
//没有返回值
arr.forEach((item,index,array)=>{
//执行代码
})
//参数:value数组中的当前项, index当前项的索引, array原始数组;
//数组中有几项,那么传递进去的匿名回调函数就需要执行几次;
map()方法将调用的数组的每个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值。
var ary = [12,23,24,42,1];
var res = ary.map(function (item,index,ary ) {
return item*10;
})
console.log(res);//-->[120,230,240,420,10]; 原数组拷贝了一份,并进行了修改
console.log(ary);//-->[12,23,24,42,1]; 原数组并未发生变化
fliter()方法返回的数组元素是调用的数组的一个子集。传递的函数是用来逻辑判定的:该函数返回true或false。
var arr = [73,84,56,22,100]
var newArr = arr.filter(item => item>80)
console.log(newArr,arr)//得到新数组 [84, 100]
every()和some()方法是数组的逻辑判定:它们对数组元素应用指定的函数进行判定,返回true或false。
every():如果该函数对每一项返回true,则返回true。
some():如果该函数对任一项返回true,则返回true。
var arr = [ 1, 2, 3, 4, 5, 6 ];
console.log( arr.every( function( item, index, array ){
return item > 3;
}));
//返回false
var arr = [ 1, 2, 3, 4, 5, 6 ];
console.log( arr.some( function( item, index, array ){
return item > 3;
}));
//true
reduce()和reduceRight()方法使用指定的函数将数组元素进行组合,生成单个值。
indexOf()和lastIndexOf()搜索整个数组中具有给定值的元素,返回找到的第一个元素的索引或者如果没有找到就返回-1。
indexOf() :方法可返回某个指定的字符串值在字符串中首次出现的位置。
lastIndexOf() ;方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
ES6新增:
copyWith():在当前数组内部将指定位置的元素复制到其他位置(会覆盖),返回当前数组。
第一个参数:从该位置开始替换
第二个参数:从该位置开始读取数据,可选,默认为0,负数为从后往前数
第三个参数:到该位置停止读取,默认为数组长度
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
find()和findIndex():
找到第一个符合条件的数组成员。
接受的为一个回调函数,所有数组成员依次执行该函数,直到找到第一个返回值为true的成员。
回调函数的参数:值,位置,原数组
find()返回找到的成员,findIndex()返回成员的位置
let arr =[1,5,10,15]
let a = arr.find(function(value,index,arr){
return value > 9;
})//返回 10
let b = arr.findIndex(function(value,index,arr){
return value > 9;
})//返回 2
console.log(a,b);
fill():把数组进行填充。
接受三个参数:填充的变量,开始填充的位置,填充结束的位置
let arr = [1,2,3,4,5];
arr.fill(100, 1, 3);
console.log(arr);
//[ 1, 100, 100, 4, 5 ]
entries( )、keys( )和values( ),用于遍历数组。
keys:对键名的遍历
value:对键值的遍历
entries:对键值对的遍历
let arr = [1, 2, 3, 4, 5];
console.log(Object.keys(arr));//keys:对键名的遍历
//[ '0', '1', '2', '3', '4' ]
arr.test = "hello";
console.log(Object.keys(arr));//[ '0', '1', '2', '3', '4', 'test' ]
console.log(Object.values(arr));//value:对键值的遍历
//[ 1, 2, 3, 4, 5, 'hello' ]
console.log(Object.entries(arr));//entries:对键值对的遍历
//[
//[ '0', 1 ],
//[ '1', 2 ],
//[ '2', 3 ],
//[ '3', 4 ],
//[ '4', 5 ],
//[ 'test', 'hello' ]
//]
includes():查看某个数组是否包含给定的值,与字符串的includes方法类似。
第一个参数:必选,待检查的给定值
第二个参数:可选,表示搜索的起始位置,默认为0,负数表示倒数的位置
注意:和indexOf的区别,indexOf进行了运算符的强比对,会导致对NaN误判。
let arr = [1,2,3,4,5,NaN];
console.log(arr.includes(3));//true
console.log(arr.includes(6));//false
console.log(arr.includes(NaN));//true
console.log(arr.indexOf(NaN));//-1
构造函数方法
Array.from():用于将两类对象转为真正的数组。
类似数组的对象
可遍历的对象
将标准的JSON代码转换为数组
在ES6中绝大部分的Array操作都存在于Array对象里。
一个标准的JSON数组格式,跟普通的JSON对比是key值是数组下标并且在最后多了一个length属性。只要是这种特殊的json格式都可以轻松使用ES6的语法转变成数组。
let people={
0:'zhangsan',
'1':24, //key值必须是0,1,2......可以是数字或者字符串
length:2 //必须有length这个特殊的属性
};
let trans=Array.from(people);//Array.from()方法
console.log(trans); //['zhangsan',24]
Array.of():负责把一组值、文本或者变量转换成数组。
类似数组的字符串可以用eval来转换,但效率低,所以就可以使用Array.of()方法
let arr =Array.of(3,4,5,'zhang','li');
console.log(arr);
//[3, 4, 5, "zhang","li"]