05.数组

183 阅读13分钟

之前学习的数据类型,只能存储一个值(字符串为一个值)。如果我们想存储多个值,就可以使用数组。

一.数组简介

数组(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

image-20210512164807054

语法:

    数组的长度 = 数组名.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 数组的遍历

  • 遍历:遍及所有,历经全部的意思,也被称之为迭代。

    • 对数组的每一个元素都访问一次就叫遍历。

    image-20210512165035148

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); //["唐僧", "沙和尚", "猪八戒", "孙悟空"]
  • 练习六:对一个数组中的数字进行排序(冒泡排序/选择排序)
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>练习六:对一个数组中的数字进行排序(冒泡排序/选择排序)</title>
  </head>

  <body>

  </body>
  <script>
    /* 
    练习六:对一个数组中的数字进行排序(冒泡排序/选择排序)
    解题思路:
        1.先找出一行中最小值
        2.循环起来
    */
    //冒泡排序 //从小到大排
    var arr = [10, 30, 25, 6, 8];
    var temp;
    /*
    //第一次:[10, 30, 25, 6, 8]; ->[10, 25, 6, 8,30]
    for (let index = 0; index < arr.length - 1; index++) { //4
      if (arr[index] >= arr[index + 1]) {
        temp = arr[index];
        arr[index] = arr[index + 1];
        arr[index + 1] = temp;
      }
    }
    //第二次:[10, 25, 6, 8,30]->[10,6, 8,25,30]
    for (let index = 0; index < arr.length - 1 - 1; index++) { //3
      if (arr[index] >= arr[index + 1]) {
        temp = arr[index];
        arr[index] = arr[index + 1];
        arr[index + 1] = temp;
      }
    }
    //第三次:[10,6, 8,25,30]->[6, 8,10,25,30]
    for (let index = 0; index < arr.length - 1 - 1 - 1; index++) { //2
      if (arr[index] >= arr[index + 1]) {
        temp = arr[index];
        arr[index] = arr[index + 1];
        arr[index + 1] = temp;
      }
    }
    //第四次:[6, 8,10,25,30]-》[6, 8,10,25,30]
    for (let index = 0; index < arr.length - 1 - 1 - 1 - 1; index++) { //1
      if (arr[index] >= arr[index + 1]) {
        temp = arr[index];
        arr[index] = arr[index + 1];
        arr[index + 1] = temp;
      }
    }

    */
    for (let j = 0; j < arr.length - 1; j++) { //外层循环起来
      for (let index = 0; index < arr.length - 1; index++) { //内层寻找最大值
        if (arr[index] >= arr[index + 1]) {
          temp = arr[index];
          arr[index] = arr[index + 1];
          arr[index + 1] = temp;
        }
      }
    }
    console.log(arr); //[6, 8,10,25,30]
  </script>

</html>

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)); // 打印结果:["王二","王三"]
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <Script type="text/javascript">
/* 
一.数组添加删除:
1.push();向数组最后添加一个元素
2.pop();删除数组的最后一个元素,返回被删除的内容
3.unshift():向数组的最开始添加一个元素,改变现数组
4.shift():删除数组的第一个元素,返回被删除的内容
二.队结构:先进先出
三.栈结构:先进后出
 */
var arr=["首页","详情页","购物车","结算页"];
//栈结构
/* 
arr.push("推荐页");
console.log(arr);
var deletestr=arr.pop();
console.log(deletestr);
console.log(arr); 

*/
//队结构1
/* arr.unshift("电脑主机页");
console.log(arr);
arr.pop();
console.log(arr); */
//队结构2
arr.push("手机页");
console.log(arr);
arr.shift();
console.log(arr);

</Script>
</head>
<body>
  
</body>
</html>

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]