之前学习的数据类型,只能存储一个值(字符串为一个值)。如果我们想存储多个值,就可以使用数组。
一.数组简介
数组(Array)是属于内置对象,我们可以在MDN网站上查询各种方法。
数组和普通对象的功能类似,也是用来存储一些值的。不同的是:
- 普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引来操作元素。索引:从0开始的整数就是索引。
- 数组的存储性能比普通对象要好。在实际开发中我们经常使用数组来存储一些数据,使用频率非常高。
二.数组的基本操作
- 数组的元素可以是任意的数据类型,也可以是对象,也可以是函数,也可以是数组。
- 数组的元素中,如果存放的是数组,我们就称这种数组为二维数组。
2.1 创建数组对象
方式一:字面量定义。举例:
var arr1=["北京","上海","广州","深圳"];
方式二:对象定义(数组的构造函数)。
语法:
var arr2=new Array(123,true,"老色笔",null,undefined,["abc","def","xyz"],{name:"小王",age:20,like:function(){console.log("钓鱼")}});
如果参数为空,则表示创建一个空数组;参数位置是一个数值时,表示数组长度;参数位置是多个数值时,表示数组中的元素。
上面的两种方式,我来举个例子:
// 方式一
var arr1 = [11, 12, 13];
// 方式二
var arr2 = new Array(); // 参数为空
var arr3 = new Array(4); // 参数为一个数值
var arr4 = new Array(15, 16, 17); // 参数为多个数值
console.log(typeof arr1); // 打印结果:object
console.log("arr1 = " + JSON.stringify(arr1));
console.log("arr2 = " + JSON.stringify(arr2));
console.log("arr3 = " + JSON.stringify(arr3));
console.log("arr4 = " + JSON.stringify(arr4));
打印结果:
object
arr1 = [11,12,13]
arr2 = []
arr3 = [null,null,null,null]
arr4 = [15,16,17]
从上方打印结果的第一行里,可以看出,数组的类型其实也是属于对象。
2.2 向数组中添加元素
语法:
数组[索引] = 值
代码举例:
var arr1 = [];
// 向数组中添加元素
arr[0] = 10;
arr[1] = 33;
arr[2] = 22;
arr[3] = 44;
2.3 获取数组中的元素
语法:
数组[索引]
数组的索引代表的是数组中的元素在数组中的位置,从0开始。
如果读取不存在的索引(比如元素没那么多),系统不会报错,而是返回undefined。
代码举例:
var arr = [21, 22, 23];
console.log(arr[0]); // 打印结果:21
console.log(arr[5]); // 打印结果:undefined
2.4 获取数组的长度
可以使用length
属性来获取数组的长度(元素的个数)。
- 获取数组某个位置的数据:通过索引值
- 索引值也被称为下标值index
- 索引值是从0开始的(注意,不是从1开始的)
- 注意:在JavaScript中获取一个不存在的索引值,不会报错,结果为undefined
语法:
数组的长度 = 数组名.length;
代码举例:
var arr = [21, 22, 23];
console.log(arr.length); // 打印结果:3
补充:
对于连续的数组,使用length可以获取到数组的长度(元素的个数);对于非连续的数组,使用length会获取到数组的最大的索引+1。因此,尽量不要创建非连续的数组。
2.5 修改数组的长度(修改length)
- 如果修改的length大于原长度,则多出部分会空出来,置为 null。
- 如果修改的length小于原长度,则多出的元素会被删除,数组将从后面删除元素。
- (特例:伪数组arguments的长度可以修改,但是不能修改里面的元素,后面单独讲。)
代码举例:
var arr1 = [11, 12, 13];
var arr2 = [21, 22, 23];
// 修改数组 arr1 的 length
arr1.length = 1;
console.log(JSON.stringify(arr1));
// 修改数组 arr2 的 length
arr2.length = 5;
console.log(JSON.stringify(arr2));
打印结果:
[11]
[21,22,23,null,null]
2.6 数组的遍历
-
遍历:遍及所有,历经全部的意思,也被称之为迭代。
- 对数组的每一个元素都访问一次就叫遍历。
2.6.1 数组的遍历练习:
-
练习一:反向遍历数组里面的每一个元素
var arr = ['孙悟空', '猪八戒', '沙和尚', '唐僧']; for (let index = arr.length - 1; index >= 0; index--) { console.log(arr[index]) }
-
练习二:将数组中所有的元素用-进行分割,拼接成一个字符串
var arr = ['孙悟空', '猪八戒', '沙和尚', '唐僧']; var str = ''; for (let index = 0; index < arr.length; index++) { if (index == arr.length - 1) { str += arr[index]; break; } else { str += arr[index] + '-'; } } console.log(str)
-
练习三:求一个数字的数字中所有数字的和和平均数
var arr = [10, 30, 25, 6, 8]; var sum = 0; for (var i = 0; i < arr.length; i++) { // debugger sum += arr[i]; } var averageNum = sum / arr.length; console.log(averageNum); //15.8
- 练习四:从一个都是数字的数组中,找出里面的最大值(作业:求最小值)
var arr = [10, 30, 25, 6, 8];
var max = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= max) {
max = arr[i];
}
}
console.log(max);//30
- 练习五:反转一个数组中的内容
var arr = ['孙悟空', '猪八戒', '沙和尚', '唐僧'];
//解法一:新数组+push
var newArr = [];
for (let index = arr.length - 1; index >= 0; index--) {
newArr.push(arr[index]);
}
console.log(newArr); //["唐僧", "沙和尚", "猪八戒", "孙悟空"]
//解法二:reverse()
// arr.reverse();
// console.log(arr)
//解法三:原数组上做变换
var temp;
for (var i = 0; i < arr.length / 2; i++) {
temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
console.log(arr); //["唐僧", "沙和尚", "猪八戒", "孙悟空"]
- 练习六:对一个数组中的数字进行排序(冒泡排序/选择排序)
练习六:对一个数组中的数字进行排序(冒泡排序/选择排序)
2.6.2 数组的排序: 排序算法
- 冒泡排序/选择排序/插入排序
- 堆排序/希尔排序/快速排序
三.数组的方法
数组的四个基本方法如下:(数组元素的添加和删除)
方法 | 描述 | 备注 |
---|---|---|
push() | 向数组的最后面插入一个或多个元素,返回结果为该数组新的长度 | 会改变原数组 |
pop() | 删除数组中的最后一个元素,返回结果为被删除的元素 | 会改变原数组 |
unshift() | 在数组最前面插入一个或多个元素,返回结果为该数组新的长度 | 会改变原数组 |
shift() | 删除数组中的第一个元素,返回结果为被删除的元素 | 会改变原数组 |
数组的常见方法如下:
方法 | 描述 | 备注 |
---|---|---|
slice() | 从数组中提取指定的一个或多个元素,返回结果为新的数组 | 不会改变原数组 |
splice() | 从数组中删除指定的一个或多个元素,返回结果为新的数组 | 会改变原数组 |
concat() | 连接两个或多个数组,返回结果为新的数组 | 不会改变原数组 |
join() | 将数组转换为字符串,返回结果为转换后的字符串 | 不会改变原数组 |
reverse() | 反转数组,返回结果为反转后的数组 | 会改变原数组 |
sort() | 对数组的元素,默认按照Unicode编码,从小到大进行排序 | 会改变原数组 |
遍历数组的方法如下:
方法 | 描述 | 备注 |
---|---|---|
for循环 | 这个大家都懂 | |
forEach() | 和 for循环类似,但需要兼容IE8以上 | forEach() 没有返回值。也就是说,它的返回值是 undefined |
map() | 对原数组中的每一项进行加工,将组成新的数组 | 不会改变原数组 |
filter() | 对数组中每一项运行回调函数,该函数返回结果是true的项,将组成新的数组,返回结果为新的数组。可以起到过滤的作用 | 不会改变原数组 |
every() | 如果有一项返回false,则停止遍历,此方法返回 false | 一假即假。要求每一项都返回true,最终的结果才返回true |
some() | 只要有一项返回true,则停止遍历,此方法返回true | 一真即真。要求每一项都返回false,最终的结果才返回false |
reduce | 为数组中的每一个元素,依次执行回调函数 |
数组的其他方法如下:
方法 | 描述 | 备注 |
---|---|---|
indexOf(value) | 从前往后索引,获取 value 在数组中的第一个下标 | |
lastIndexOf(value) | 从后往前索引,获取 value 在数组中的最后一个下标 | |
find(function()) | 找出第一个满足「指定条件返回true」的元素。 | |
findIndex(function()) | 找出第一个满足「指定条件返回true」的元素的index | |
Array.from(arrayLike) | 将伪数组转化为真数组 | |
Array.of(value1, value2, value3) | 将一系列值转换成数组。 |
3.1 数组的队结构和栈结构
push()
push()
:向数组的最后面插入一个或多个元素,返回结果为该数组新的长度。
语法:
数组的新长度 = 数组.push(元素);
代码举例:
var arr = ["王一", "王二", "王三"];
var result1 = arr.push("王四"); // 末尾插入一个元素
var result2 = arr.push("王五", "王六"); // 末尾插入多个元素
console.log(result1); // 打印结果:4
console.log(result2); // 打印结果:6
console.log(JSON.stringify(arr)); // 打印结果:["王一","王二","王三","王四","王五","王六"]
pop()
pop()
:删除数组中的最后一个元素,返回结果为被删除的元素。
语法:
被删除的元素 = 数组.pop();
代码举例:
var arr = ["王一", "王二", "王三"];
var result1 = arr.pop();
console.log(result1); // 打印结果:王三
console.log(JSON.stringify(arr)); // 打印结果:["王一","王二"]
unshift()
unshift()
:在数组最前面插入一个或多个元素,返回结果为该数组新的长度。插入元素后,其他元素的索引会依次调整。
语法:
数组的新长度 = 数组.unshift(元素);
代码举例:
var arr = ["王一", "王二", "王三"];
var result1 = arr.unshift("王四"); // 最前面插入一个元素
var result2 = arr.unshift("王五", "王六"); // 最前面插入多个元素
console.log(result1); // 打印结果:4
console.log(result2); // 打印结果:6
console.log(JSON.stringify(arr)); // 打印结果:["王五","王六","王四","王一","王二","王三"]
shift()
shift()
:删除数组中的第一个元素,返回结果为被删除的元素。
语法:
被删除的元素 = 数组.shift();
代码举例:
var arr = ["王一", "王二", "王三"];
var result1 = arr.shift();
console.log(result1); // 打印结果:王一
console.log(JSON.stringify(arr)); // 打印结果:["王二","王三"]
Document
3.2 数组的常用方法
1.slice()
slice()
:从数组中提取指定的一个或者多个元素,返回结果为新的数组(不会改变原来的数组)。
备注:该方法不会改变原数组,而是将截取到的元素封装到一个新数组中返回。
语法:
新数组 = 原数组.slice(开始位置的索引, 结束位置的索引); //注意:包含开始索引,不包含结束索引
==补充==:
很多前端开发人员会用 slice()将伪数组,转化为真数组。写法如下:
array = Array.prototye.slice.call(arrayLike)
或者
array = [].slice.call(arrayLike)
ES6 看不下去这种蹩脚的转化方法,于是出了一个新的 API:(专门用来将伪数组转化成真数组)
array = Array.from(arrayLike)
var arr = ["蔡徐坤", "范丞丞", "周震南", "小鬼"];
//1.slice(start index,end index):从数组中提取一个或多个元素,结果返回数组【左闭右开】
var newArr = arr.slice(0, 1);
console.log(newArr);//["蔡徐坤']
console.log(arr);//[ "范丞丞", "周震南", "小鬼"];
2.Splice()
splice()
:从数组中替换/删除指定的一个或多个元素,返回结果为新的数组(会改变原来的数组)。
备注:该方法会改变原数组,会将指定元素从原数组中删除;被删除的元素会封装到一个新的数组中返回。
语法:
新数组 = 原数组.splice(起始索引index, 需要删除的个数, 第三个参数, 第四个参数...);
上方语法中,第三个及之后的参数,表示:向原数组中添加新的元素,这些元素将会自动插入到开始位置索引的前面。
/2.splice(start index,deleteDetail):删除
var newArr1 = arr.splice(0, 1);
console.log(newArr1);//["蔡徐坤']
console.log(arr);//[ "范丞丞", "周震南", "小鬼"];
// splice(start index,deleteDetail,replaceMent):替换
var newArr1 = arr.splice(0, 1, "虞书欣", "大嘴");
console.log(newArr1);//["蔡徐坤']
console.log(arr);//["虞书欣", "大嘴","范丞丞", "周震南", "小鬼"];
3.concat()
concat()
:连接两个或多个数组,返回结果为新的数组。(不会改变原数组)
语法:
新数组 = 数组1.concat(数组2, 数组3 ...);
//3.concat():将两个数组拼接为一个
var arr2 = [1, 2, 3];
var arr3 = arr.concat(arr2);
console.log(arr3);//["蔡徐坤", "范丞丞", "周震南", "小鬼", 1, 2, 3]
4.join()
join()
:将数组转换为字符串,返回结果为转换后的字符串(不会改变原来的数组)。
补充:join()
方法可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符;如果不指定连接符,则默认使用 ,
作为连接符,此时和 toString()的效果是一致的
。
语法:
新的字符串 = 原数组.join(参数); // 参数选填
/4.join():将一个数组转换为字符串,默认以逗号隔开,也可以传特殊符号隔开
//var str=arr.join("*");
var str=arr.toString();
console.log(str);//蔡徐坤,范丞丞,周震南,小鬼
5.reverse()
reverse()
:反转数组,返回结果为反转后的数组(会改变原来的数组)。
语法:
反转后的数组 = 数组.reverse();
举例:
var arr = ["a", "b", "c", "d", "e", "f"];
var result = arr.reverse(); // 将数组 arr 进行反转
console.log("arr =" + JSON.stringify(arr));
console.log("result =" + JSON.stringify(result));
打印结果:
arr =["f","e","d","c","b","a"]
result =["f","e","d","c","b","a"]
从打印结果可以看出,原来的数组已经被改变了。
6.sort( )
sort()方法要好好理解。所以,我们单独用一大段来讲。
sort()
:对数组的元素进行从小到大来排序(会改变原来的数组)。
==sort()方法举例:无参时==
如果在使用 sort() 方法时不带参,则默认按照Unicode编码,从小到大进行排序。
举例1:(当数组中的元素为字符串时)
var arr1 = ["e", "b", "d", "a", "f", "c"];
var result = arr1.sort(); // 将数组 arr1 进行排序
console.log("arr1 =" + JSON.stringify(arr1));
console.log("result =" + JSON.stringify(result));
打印结果:
arr1 =["a","b","c","d","e","f"]
result =["a","b","c","d","e","f"]
举例2:(当数组中的元素为数字时)
var arr2 = [5, 2, 11, 3, 4, 1];
var result = arr2.sort(); // 将数组 arr2 进行排序
console.log("arr2 =" + JSON.stringify(arr2));
console.log("result =" + JSON.stringify(result));
打印结果:
arr2 =[1,11,2,3,4,5]
result =[1,11,2,3,4,5]
上方的打印结果中,你会发现,使用 sort() 排序后,数字11
竟然在数字2
的前面。这是为啥呢?因为上面讲到了,sort()
方法是按照Unicode编码进行排序的。
那如果我想让 arr2 里的数字,完全按照从小到大排序,怎么操作呢?继续往下看。
==sort()方法举例:带参时==
如果在 sort()方法中带参,我们就可以自定义排序规则。具体做法如下:
我们可以在sort()添加一个回调函数,来指定排序规则。回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数
浏览器根据回调函数的返回值来决定元素的排序:(重要)
- 如果返回一个大于0的值,则元素会交换位置
- 如果返回一个小于0的值,则元素位置不变
- 如果返回一个0,则认为两个元素相等,则不交换位置
代码举例:
var arr3 = [5, 2, 11, 3, 4, 1];
// 自定义排序规则
var result = arr3.sort(function(a, b) {
if (a > b) { // 如果 a 大于 b,则交换 a 和 b 的位置
return 1;
} else if (a < b) { // 如果 a 小于 b,则位置不变
return -1;
} else { // 如果 a 等于 b,则位置不变
return 0;
}
});
console.log("arr3 =" + JSON.stringify(arr3));
console.log("result =" + JSON.stringify(result));
打印结果:
arr3 =[1,2,3,4,5,11]
result =[1,2,3,4,5,11]
上方代码的写法太啰嗦了,其实也可以简化为如下写法:
代码优化:(冒泡排序)
var arr3 = [5, 2, 11, 3, 4, 1];
// 自定义排序规则
var result = arr3.sort(function(a, b) {
return a - b; // 升序排列
// return b - a; // 降序排列
});
console.log("arr3 =" + JSON.stringify(arr3));
console.log("result =" + JSON.stringify(result));
打印结果:
arr3 =[1,2,3,4,5,11]
result =[1,2,3,4,5,11]