Skip to content
on this page

扫码联系

编程学习&& IT

tian

内置对象简介

JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象。

前面两种对象:是JS的基础内容,属于 ECMAScript; 第三个浏览器对象:属于JS独有,即 JS 内置的API。

内置对象:就是指这个语言自带的一些对象,供开发者使用,这些对象提供了一些常用或者最基本而必要的功能(属性和方法)。

内置对象最大的优点就是帮助我们快速开发。

JavaScript的内置对象

内置对象对象说明
Arguments函数参数集合
Array数组
Boolean布尔对象
Math数学对象
Date日期时间
Error异常对象
Function函数构造器
Number数值对象
Object基础对象
RegExp正则表达式对象
String字符串对象

1.什么是数组

编程时,我们经常会遇见处理“—组数值”的情况,比如全班10个学生的考试成绩

js
let a0 = 96,a1 = 97, a2 = 76,a3 = 87,a4 = 87,a5 = 90, a6 = 91, a7 = 100,a8 = 78,a9 = 56;
//错误的做法
//无法对这些数据进行批量操作  比如计算这些数据的总和和平均分  for循环无从下手

数组(Array),顾名思义,用来存储一组相关的值,从而方便进行求和、计算平均数、逐项遍历等操作。

js
let scoreArr = [96, 97, 76, 87, 87, 90, 91, 100, 78, 56];

每种高级编程语言中都有数组,它是非常重要的一种数据结构

数组的存储性能比普通对象要好。在实际开发中我们经常使用数组来存储一些数据(尤其是列表数据),使用频率非常高。

比如说,上面这个页面的列表数据,它的结构就是一个大数组。

数组中的元素可以是任意的数据类型,也可以是对象,也可以是函数,也可以是数组。数组的元素中,如果存放的是数组,我们就称这种数组为二维数组。

接下来,我们讲一讲数组的基本操作。

2.数组的定义和简介

定义方法1

使用数组字面量表示法

由一对包含数组项的方括号 [] 表示, 多个数组项之间以逗号隔开。

最简单,也用得最多。

js
let arr1 = []; // 创建一个空的数组

let arr2 = ["A" , "B" , "C" , "D"]; //有四项 长度为4

定义方法2

使用Array构造函数

如果参数是一个数值时,表示数组的长度;如果有多个参数时,表示数组中的元素。

js
let arr = new Array("A" , "B" , "C" , "D");

注意这种方法如果我们只写一个数字作为参数

js
let arr = new Array(4);

console.log(arr.length); //4
// 表示生成一个四个项的数组,每个位置都是空值。


//Array()作为构造函数,行为很不一致。
//因此,不建议使用它生成新数组,直接使用数组字面量是更好的做法。

定义方法3

Array.of():创建数组

语法

js
Array.of(value1, value2, value3);

作用:根据参数里的内容,创建数组。

举例

js
let arr = Array.of(1, 'abc', true);
console.log(arr); // 打印结果是数组:[1, "abc", true]

补充:new Array()Array.of()的区别在于:

当参数只有一个时,前者表示数组的长度,后者表示数组中的内容。

访问数组项

数组每一项都有下标 , 下标从0开始

js
let arr = ["A" , "B" , "C" , "D"]; //下标分别是  0  1  2  3

使用方括号中 书写下标 的形式 访问数组的项

js
let arr = ["A" , "B" , "C" , "D"];


console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
console.log(arr[3]);
console.log(arr);

下标越界

JavaScript规定,访问数组中不存在的项会返回undefined,不会报错

js
let arr = ["A" , "B" , "C" , "D"];

console.log(arr[4]); //undefined
console.log(arr[10000]); //undefined
console.log(arr[-1]); //undefined

更改数组项

数组并不是只读的,我们可以修改它其中任何项的值

js
let arr = [2 , 0 , 2 , 0];

arr[0]++;
arr[1] = 6;
console.log(arr); // 3 6 2 0

如果更改的数组项超过了length-1,则会创造这项

js
let arr = [2 , 0 , 2 , 0];

arr[6] = 6;

console.log(arr);

0k8SaV.png

数组的长度

数组的length属性表示它的长度

数组最后一项的下标是数组的长度减1

js
let arr = ["A" , "B" , "C" , "D"];

console.log(arr.length); //4
console.log(arr[arr.length - 1]) //D

length属性是可写的。

如果人为设置length小于当前成员个数的值,该数组的成员数量会自动减少到length设置的值。

js
let arr = [1,2,3,4];

console.log(arr.length); //4

arr.length = 2;
console.log(arr); // [1, 2]  数组长度可改变 数组内容也发生改变

人为设置length大于当前元素个数,则数组的成员数量会增加到这个值新增的位置都是空位。

js
let a = ['a'];
a.length = 3;
console.log(a[2]);// undefined

清空数组的一个有效方法,就是将**length属性设为0。**

数组的遍历

数组的最大的优点就是方便遍历

js
let arr = ["A" , "B" , "C" , "D"];

for(let i = 0; i < arr.length; i++){
    console.log(arr[i]);
}

数组的检测

Array.isArray方法返回一个布尔值,表示参数是否为数组。

可以弥补typeof运算符的不足。

js
let arr = [1, 2, 3];


console.log( typeof arr );// "object"
console.log( Array.isArray(arr));// true

//typeof运算符只能显示数组的类型是Object
//而Array.isArray方法可以识别数组。
html
<body>
    <p></p>
    <p></p>
    <p></p>

    <script>
        let a = 3;
        let b = document.querySelectorAll("p")
        console.log(Array.isArray(a));//false 
        console.log(Array.isArray(b));//false 
        //类数组不能检测
    </script>
</body>

toString()

数组转换为字符串

字符串 = 数组.toString();

解释:把数组转换成字符串,每一项用,分割。

备注:大多数的数据类型都可以使用.toString()方法,将其转换为字符串。

**知识点补充:**将数组转换为字符串,有哪些方式

方式 1:

js
字符串 = 数组.toString();

方式 2:

js
字符串 = String(数组);

方式 3:

js
字符串 = 数组.join(',');  //  将数组转为字符串,每一项用 英文逗号 分隔

Array.from()

作用:将伪数组或可遍历对象转换为真数组。

可遍历的 ===> 数组,字符串,Set.Map.NodeList,arguments以及拥有length属性的任意对象

另外,伪数组的原型链中没有 Array.prototype,而真数组的原型链中有 Array.prototype。因此伪数组没有数组的一般方法,比如 pop()、join() 等方法。

语法

js
array = Array.from(arrayLike);
js
let name = 'yunmudsb';
console.log(Array.from(name)); // 打印结果是数组:["y","u","n","m","u","d","s","b"]

伪数组举例

html
<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>

    <script>
        let btnArray = document.getElementsByTagName('button');
        console.log(btnArray);
        console.log(Array.isArray(btnArray));
    </script>
</body>

上面的布局中,有三个 button 标签,我们通过getElementsByTagName获取到的btnArray实际上是伪数组,并不是真实的数组:

0U3mDS.png

既然btnArray是伪数组,它就不能使用数组的一般方法,否则会报错:

解决办法:采用Array.from方法将btnArray这个伪数组转换为真数组即可:

js
Array.from(btnArray);

然后就可以使用数组的一般方法了:

0U3PNd.png

3.数组的方法

数组的头尾操作方法

0kGHXj.png

push方法

push()方法用来在数组末尾推入新项,参数就是要推入的项 , 并返回添加新元素后的数组长度

如果要推入多项,可以用逗号隔开

调用push()方法后,原先数组会立即改变,不需要赋值

语法:

js
新数组的长度 = 数组.push(元素);
js
let arr = [11, 22, 33, 44];
// 方法就是打点调用的函数 , 所以是数组打点调用他们
arr.push(55);
arr.push(66);
arr.push(77 , 88)
console.log(arr); // [11, 22, 33, 44, 55, 66, 77, 88]

pop方法

用于删除数组的最后一个元素,并返回被删除的这个元素

注意,该方法会改变原数组

语法:

js
被删除的元素 = 数组.pop();
js
let arr = [11, 22, 33, 44];
// 方法就是打点调用的函数 , 所以是数组打点调用他们
let del = arr.pop();

console.log(arr); //[11, 22, 33]
console.log(del); //44

unshift()方法

用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。插入元素后,其他元素的索引会依次调整。

注意,该方法会改变原数组。

js
let arr = [1 , 8 , 9 ,16];
let size = arr.unshift(100 , 110);
console.log(arr); //[100, 110, 1, 8, 9, 16]
console.log(size); //6

//unshift()方法可以接受多个参数,这些参数都会添加到目标数组头部。

shift()

删除数组中的第一个元素,返回结果为被删除的元素

注意,该方法会改变原数组

js
let arr = ["tian", "夕颜", "大鱼"];

let del = arr.shift();

console.log(arr); //["夕颜", "大鱼"]

console.log(del); //tian

splice()

splice()方法用于替换数组中的指定项

注意,该方法会改变原数组。

语法:

js
新数组 = 原数组.splice (删除起始索引index(从0开始), 需要删除的个数);

新数组 = 原数组.splice(删除起始索引index(从0开始), 需要删除的个数, 新的元素1, 新的元素2...);

//上方语法中,第三个及之后的参数,表示:删除元素之后,向原数组中添加新的元素,这些元素将会自动插入到起始位置索引的前面。也可以理解成:删除了哪些元素,就在那些元素的所在位置补充新的内容

slice()方法和splice()方法很容易搞混,请一定要注意区分。

举例 1:

js
let  arr1 = ["a" , "b" , "c" , "d"];

//只写一个参数默认从起始索引(包含)往后删除
arr1.splice(1); 

console.log(arr1);//["a"]

举例 2:

js
let arr2 = ['a', 'b', 'c', 'd', 'e', 'f'];
arr2.splice(-2); //删除最后两个元素
console.log(arr2); //["a", "b", "c", "d"]

举例 3:

js
let arr3 = ['a', 'b', 'c', 'd', 'e', 'f'];
arr3.splice(1, 3); //从索引为1的位置(包含)开始删除元素,一共删除三个元素
console.log(arr3); // ["a", "e", "f"]

举例 4:(我们来看看第三个参数的用法)在指定位置插入新项

js
let arr4 = [11, 22, 33, 44 , 55, 66];

arr4.splice(3, 0, 99, 88, 77);  //插入原来下标为3的项的前面

console.log(arr4);//[11, 22, 33, 99, 88, 77, 44, 55, 66]

举例 5:

js
let arr5 = ['a', 'b', 'c', 'd', 'e', 'f'];

//从第index为1的位置开始删除元素,一共删除三个元素。并且在 index=1 的前面追加两个元素
arr5.splice(1, 3, 'tian', '夕颜');

console.log(arr5); //["a", "tian", "夕颜", "e", "f"]

splice()方法会以数组形式返回被删除替换的项

js
let  arr = ["a" , "b" , "c" , "d"];

let newArr = arr.splice(1 , 2); 

console.log(newArr);// ["b" , "c"]

slice()

slice()方法用于得到子数组

slice(a,b)截取的子数组从下标为a的项开始,到下标为b(但不包括下标为b的项)结束

返回一个新数组,原数组不变。

slice()如果不提供第二个参数,则表示从指定项开始,提取所有后续所有项作为子数组

slice()方法的参数允许为负数,表示数组的倒数第几项

js
let colors = ["red" , "green" , "blue" , "yellow"];

let newColors1 = colors.slice();// 不加参数时,则获取所有的元素。相当于数组的整体赋值
let newColors2 = colors.slice(1); // 从第一个值开始提取,直到末尾
let newColors3 = colors.slice(-2);// 提取最后两个元素 
//如果slice方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置。
let newColors4 = colors.slice(2 , 4); // 提取从第二个到第四个之间的元素(不包括第四个元素)
let newColors5 = colors.slice(4, 2);   // 空
let newColors6 = colors.slice(2 , -1); 

console.log(newColors1);
console.log(newColors2);
console.log(newColors3);
console.log(newColors4);
console.log(newColors5);
console.log(newColors6);
//结果如下图

0UtkOx.md.png

fill()

fill():用一个固定值填充数组,返回结果为新的数组。不会改变原数组。

js
// 用一个固定值填充数组。数组里的每个元素都会被这个固定值填充
新数组 = 数组.fill(固定值);

// 从 startIndex 开始的数组元素,用固定值填充
新数组 = 数组.fill(固定值, startIndex);

// 从 startIndex 到 endIndex 之间的元素(包左不包右),用固定值填充
新数组 = 数组.fill(固定值, startIndex, endIndex);

举例:

js
// 创建一个长度为4的空数组,然后用 'f' 来填充这个空数组
console.log(Array(4).fill('f')); // ['f', 'f', 'f,' 'f']

// 将现有数组的每一个元素都进行填充
console.log(['a', 'b', 'c', 'd'].fill('f')); // ['f', 'f', 'f,' 'f']

 console.log(['a', 'b', 'c', 'd'].fill('f' , 1)); // ["a", "f", "f", "f"]

// 指定位置进行填充
console.log(['a', 'b', 'c', 'd'].fill('f', 1, 3)); // ["a", "f", "f", "d"]

join()和split()

数组的join()方法可以 使数组转为字符串; 不改变原数组

字符串的split()方法可以 使字符串转为数组。 不改变原字符串

0Aif4x.png

join()的参数表示以什么字符作为连接符,如果留空则默认以逗号分隔,如同调用toString()方法

js
let arr  = [11, 22, 33, 44];

let newStr = arr.join();  //等同于arr.join(",");

console.log(newStr); //11,22,33,44

//如同arr.toString();
js
let newStr = arr.join("");

console.log(newStr);  //11223344
js
let newStr = arr.join("-");

console.log(newStr); //11-22-33-44
js
let newStr = arr.join("");

console.log(newStr); //11❤22❤33❤44
js
let newStr = arr.join("|")
console.log(newStr); //11|22|33|44

split()的参数表示以什么字符拆分字符串一般不能留空

注意,split()是字符串的方法,不是数组的方法。

代码举例 1

js
//如果省略参数,则返回数组的唯一成员就是原字符串。
let str  = "abcdefg";

let newArr = str.split();

console.log(newArr);  //["abcdefg"]  数组只有原来字符串这一项

代码举例 2

js
let str = 'yunmu, mu, shuai, bi'; // 用逗号隔开的字符串

let newArr = str.split(','); // 将字符串 str 拆分成数组,通过逗号来拆分

console.log(newArr);  // ["yunmu", " mu", " shuai", " bi"]

代表举例 3:

js
let str = "2020-11-11";


console.log(str.split());
// 无参数,表示:把整个字符串作为一个元素添加到数组中。

console.log(str.split(""));
// 参数为空字符串,则表示:分隔字符串中每一个字符,分别添加到数组中

console.log(str.split("-"));
// 参数为指定字符,表示:用 '-' 分隔字符串。此分隔符将不会出现在数组的任意一个元素中

console.log(str.split('0'));
// 同上

0URgL8.png

备注split()这个方法在实际开发中用得非常多。一般来说,从接口拿到的 json 数据中,经常会收到类似于"y, u, n"这样的字符串,前端需要将这个字符串拆分成['y', 'u', 'n']数组,这个时候split()方法就派上用场了

concat方法

concat方法用于多个数组的合并。

它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。

js
let arr1 = ["a" , "b", "c" , "d" , "e"];
let arr2 = ["f" , "g"];
let arr3 = ["h"];
let newArr = arr1.concat(arr2 , arr3 , [1 , 2 , 3]);
console.log(newArr); // ["a", "b", "c", "d", "e", "f", "g", "h", 1, 2, 3]
js
['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]

sort()

数组排序可以使用sort()方法 , 这个方法的参数又是一个函数。

sort()方法不是按照大小排序,默认是按照字典顺序排序。数值会被先转成字符串,再按照字典顺序进行比较,排序后,原数组将被改变。

sort()方法:无参时

举例 1:(当数组中的元素为字符串时)

js
let arr1 = ['e', 'b', 'd', 'a', 'f', 'c'];

arr1.sort(); // 将数组 arr1 进行排序

console.log(arr1); //["a","b","c","d","e","f"]

举例 2:(当数组中的元素为数字时)

如果在使用 sort() 方法时不带参,则默认按照Unicode 编码,从小到大进行排序。

js
let arr2 = [5, 2, 11, 3, 4, 1];

arr2.sort(); // 将数组 arr2 进行排序

console.log(arr2); //[1,11,2,3,4,5]

上方的打印结果中,你会发现,使用 sort() 排序后,数字11竟然在数字2的前面。这是为啥呢?因为上面讲到了,sort()方法是按照Unicode 编码进行排序的。

那如果我想让 arr2 里的数字,完全按照从小到大排序,怎么操作呢?继续往下看

sort()方法:带参时,自定义排序规则

如果在 sort()方法中带参,我们就可以自定义排序规则。具体做法如下:

sort的参数函数本身接受两个参数,表示进行比较的两个数组成员。如果该函数的返回值大于0,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面。

浏览器根据回调函数的返回值return来决定元素的排序:(重要)

  • 如果返回一个大于 0 的值,则元素会交换位置
  • 如果返回一个小于 0 的值,则元素位置不变
  • 如果返回一个等于 0 的值,则认为两个元素相等,则不交换位置

如果只是看上面的文字,可能不太好理解,我们来看看下面的例子,你肯定就能明白。

举例:将数组中的数字按照从小到大排序

写法 1

js
let arr = [5, 2, 11, 3, 4, 1];

// 自定义排序规则
//这个函数中的a、b分别表示数组中靠前和靠后的项
arr.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(arr); //[1, 2, 3, 4, 5, 11]

写法2

js
arr.sort(function(a , b){ return a - b; }) //会使得原数组变成升序
arr.sort(function(a , b){ return  b - a; }) //会使得原数组变成降序
console.log(arr);

反序

js
arr.sort(function(a , b) { return -1 } )
console.log(arr); //使得原数组反序

随机排序

js
arr.sort(function(a , b){  return Math.random() - 0.5;  }) 
console.log(arr);

sort 方法举例:将数组从小到大排序

将数组从小到大排序,这个例子很常见。但在实际开发中,总会有一些花样。

下面这段代码,在实际开发中,经常用到,一定要掌握。完整代码如下:

html
<script>
    let dataList = [
        {
            title: "品牌鞋子,高品质低价入手",
            publishTime: 200,
        },
        {
            title: "不是很贵,但是很暖",
            publishTime: 100,
        },
        {
            title: "无法拒绝的美食,跟我一起吃吃",
            publishTime: 300,
        },
    ];

    console.log("yunmudsb 排序前的数组:", dataList);

    // 将dataList 数组,按照 publishTime 字段,从小到大排序。(会改变原数组)
    dataList.sort(function (a, b) {
        return parseInt(a.publishTime) - parseInt(b.publishTime);
        //一般是后台接口返回给前端的 统一先做一次 partInt() 比较保险。这是一种良好的工作习惯。
    });

    console.log("yunmudsb 排序后的数组", dataList);
</script>
js
yunmudsb 排序前的数组: [
    {"title":"品牌鞋子,高品质低价入手","publishTime":200},
    {"title":"不是很贵,但是很暖","publishTime":100},
    {"title":"无法拒绝的美食,跟我一起吃吃","publishTime":300}
]

yunmudsb 排序后的数组: [
    {"title":"不是很贵,但是很暖","publishTime":100},
    {"title":"品牌鞋子,高品质低价入手","publishTime":200},
    {"title":"无法拒绝的美食,跟我一起吃吃","publishTime":300}
]

reverse()

reverse方法用于置反排列数组元素,返回改变后的数组。

注意,该方法将改变原数组

语法:

反转后的数组 = 数组.reverse();

举例:

js
let a = ['a', 'b', 'c'];

let b = a.reverse(); 
console.log(a);// ["c", "b", "a"]
console.log(b);// ["c", "b", "a"]

题目

如何把ABCDEFG字符串置反

js
let str = "ABCDEFG";

let newArr =  str.split("");

newArr.reverse();

let newStr = newArr.join("");

console.log(newArr); //["G", "F", "E", "D", "C", "B", "A"]
 
console.log(newStr); //GFEDCBA

indexOf()和 lastIndexOf()

indexof()方法的功能是搜索数组中的元素,并返回它所在的位置,如果元素不存在,则返回-1

语法 1

js
索引值 = 数组.indexOf(想要查询的元素);

索引值 = 数组.lastIndexOf(想要查询的元素);

备注:indexOf() 是从前向后查找元素的位置。

​ 同理,lastIndexOf()是从后向前寻找。返回给定元素在数组中最后一次出现的位置

这个方法的作用:

  • 如果获取的索引值为 0,说明数组是以查询的元素为开头的
  • 如果获取的索引值为-1,说明这个数组中没有指定的元素。

注意indexOf()在检索时,是严格类型约束,类似于===

js
let arr = ['a', 'b', 'c', 'd', 'e', 'd', 'c'];

console.log(arr.indexOf('c')); // 2  从前往后,找第一个"c"在哪个位置
console.log(arr.lastIndexOf('d')); // 5 从后往前,找第一个"d"在哪个位置
js
let pos = arr.indexOf(100);

console.log(pos);//-1  没有查找到为-1

注意,这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN

js
[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1

//这是因为这两个方法内部,使用严格相等运算符(===)进行比较,而NaN是唯一一个不等于自身的值。

语法 2

indexOf方法还可以接受第二个参数,表示搜索的开始位置。

js
索引值 = 数组.indexOf(想要查询的元素, [起始位置]);
js
let arr = ['q', 'i', 'a', 'n', 'g', 'u', 'y', 'i', 'h', 'a', 'o'];
let result = arr.indexOf('a', 3); // 从第三个位置开始查找 'a'这个元素 【重要】
console.log(result); // 打印结果:9

includes()

includes()方法的功能是判断一个数组是否包含一个指定的值,返回布尔值

语法

js
布尔值 = arr.includes(想要查找的元素, [position]);
js
const arr = [11, 12, 13, 14, 15];

console.log(arr.includes(12)); // 打印结果:true
console.log(name.includes(20)); // 打印结果:false

console.log(name.includes(11, 1)); // 打印结果:false

includes()方法的第二个参数表示搜索的起始位置,默认为0

js
console.log([1, 2, 3].includes(2));     // true
console.log([1, 2, 3].includes(4));     // false

console.log([1, 2, 3].includes(2 , 2)); // false

基本遵循严格相等(===),但是对于NaN的判断与===不同,includes认为NaN=== NaN

js
console.log(NaN === NaN); //false

console.log([1,2,3,NaN].includes(NaN)); //true

面试小题

完成以下代码段 实现b数组对a数组的拷贝 方法越多越好

js
let  a = ["123", true , 34];
let  b;
js
//方法一
b = [];
for(let i=0; i<a.length; i++){
    b.push(a[i])
}
console.log(b)
js
// 方法二
b  = [].concat(a);
console.log(b)
js
// 方法三
b = a.slice(0);
console.log(b);
js
// 方法四
b = a.splice(0); //会改变原数组

console.log(b);

4.数组遍历

遍历相关算法

题目1

求数组中每一项的总和、平均数

js
// 求数组的总和
let arr = [ 1, 2, 3, 4, 5, 6, 7,  8, 9, 10];

// 累加器
let sum = 0;

// 遍历数组  每遍历到一个数字  就把这个数字累加到累加器之中
for(let i = 0; i < arr.length; i++){
    sum += arr[i];
}
console.log(sum);
console.log(sum / arr.length);

题目2

求数组的最大值和最小值

html
<script>
    let arr = [32, 46, 23, 56, 98, 100, 1];


    // 定义两个变量  max表示当前寻找到的最大值  默认是arr[0]
    //			   min表示当前寻找到的最小值  默认是arr[0]
    let max = arr[0];

    let min = arr[0];


    //  遍历数组  从下标为1的项开始遍历
    for(let i = 1; i < arr.length; i++){
        // 如果你遍历的这项 比当前最大值大  那么就让当前最大值成为这个项
        if(arr[i] > max){
            max = arr[i];
        }else if(arr[i] < min){
            // 否则如果你遍历的这项 比当前最小值小  那么就让当前最小值成为这个项
            min = arr[i];
        }
    }
    console.log(max , min);
</script>

翻转数组

方式 1:

html
<script>
    let arr = [10, 20, 30, 40, 50]; // 原始数组
    
    
    function reverseArr(arr) {
        let newArr = [];

        for (let i = 0; i < arr.length; i++) {
            newArr[i] = arr[arr.length - i - 1];
        }

        return newArr;
    }
    console.log(reverseArr(arr));

    //或者
    function reverseArr(arr) {
        let newArr = [];

        for(let i = arr.length - 1; i >= 0; i--){
            newArr[newArr.length] = arr[i];
        }

        return newArr;
    }
</script>

方式 2:(算法里比较常见的方式)

js
function reverseArr(arr) {
    for (let i = 0; i < arr.length / 2; i++) {
        let temp = arr[i];
        arr[i] = arr[arr.length - 1 - i];
        arr[arr.length - 1 - i] = temp;
    }
    return arr;
}

清空数组

清空数组,有以下几种方式:

js
let arr = [1, 2, 3, 4, 5, 6];

arr.splice(0); //方式1:删除数组中所有项目
arr.length = 0; //方式2:length属性可以赋值,在其它语言中length是只读
arr = []; //方式3:推荐

数组去重

去掉数组中的重复项

思路:准备一个空结果数组遍历原数组,如果遍历到的项不在结果数组中,则推入结果数组

html
<script>
    let arr = [1, 2, 1, 4, 4, 3];

    // 结果数组
    let result = [];

    // 遍历原数组
    for (let i = 0; i < arr.length; i++) {
        // 判断遍历到的这项是否在结果数组中 如果不在就推入
        // includes方法用来判断某项是否在数组中
        if (!result.includes(arr[i])) {
            result.push(arr[i]);
        }
    }

    console.log(result);
</script>

随机样本

请随机从原数组中取3项

思路:准备一个空结果数组遍历原数组随机选择一项,推入结果数组,并且将这项删除

html
<script>
    let arr = [66, 77, 88, 99, 110, 120];

    // 结果数组
    let result = [];

    //   遍历三次取值
    for (let i = 0; i < 3; i++) {
        //   随机选择数组一项的下标,数组的下标是 0 ~ arr.length - 1
        //   之前学过random的公式  [a, b]区间的随机数是 parseInt(Math.random() * (b-a+1) + a);
        let n = parseInt(Math.random() * arr.length);
        // 把这项推入结果数组之中
        result.push(arr[n]);
        // 删除 这项防止被重复随机到
        arr.splice(n, 1);
    }

    console.log(result);
</script>

冒泡排序

0AqRgI.gif

实现原理

数组中有n个数,比较每相邻两个数,如果前者大于后者,就把两个数交换位置;这样一来,第一轮就

可以选出一个最大的数放在最后面;那么经过n-1(数组的length -1)趟,就完成了所有数的排序。

4个数字,共需要比较3趟,比较次数为3+2+1=6次。

n个数字,共需要比较n-1趟,比较次数为n(n-1)/2次。

我们先来实现找数组中的最大数,并把他放到数组最后。

html
<script>
    let arr = [1, 7, 8, 3, 2, 0];

    for (let j = 0; j < arr.length - 1; j++) {
        if (arr[j] > arr[j + 1]) {
            //如果前一个数大于后一个数就交换位置
            let temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
    console.log(arr);
</script>

我们能找到数组中最大的数,放到最后,这样重复 arr.length -1 次,便可以实现数组按从小到大的顺序排好了。

html
<script>
    let arr = [1, 7, 8, 3, 2, 0];
	
    //一趟一趟的比较  趟数的序号就是 i
    for (let i = 0; i < arr.length - 1; i++) {
           // 内层循环负责两两比较
        for (let j = 0; j < arr.length - 1; j++) {
            //这里的j < arr.length合适吗? 
            if (arr[j] > arr[j + 1]) {
               //如果前一项 大于后一项 就要交换两个的位置
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    console.log(arr);
</script>

虽然上面的代码已经实现冒泡排序了,但就像注释中提到的,内层 for 循环的次数写成 arr.length是不是合适?

当第一次,找到最大数,放到最后,那么下一次,遍历的时候,是不是就不能把最后一个数算上了呢?

因为他就是最大的了,不会出现,前一个数比后一个数大,要交换位置的情况,所以内层 for 循环的次数,改成 arr.length - i - 1

html
<script>
    let arr = [1, 7, 8, 3, 2, 0];
	
    //一趟一趟的比较  趟数的序号就是 i
    for (let i = 0; i < arr.length - 1; i++) {
        // 内层循环负责两两比较
        for (let j = 0; j < arr.length - i - 1; j++) {
            // 判断项的大小
            if (arr[j] > arr[j + 1]) {
                //如果前一项 大于后一项 就要交换两个的位置
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
        // 每一趟输出的数组
        console.log(arr);
    }
    console.log(arr);
</script>

总结

1、外层 for 循环控制循环次数

2、内层 for 循环进行两数交换,找每次的最大数,排到最后

二维数组

以数组作为数组元素的数组,即**“数组的数组"**

二维数组可以看做是矩阵

js
let matrix = [
    [11, 22, 33], 
    [13, 26, 37], 
    [44, 47, 48],
    [34, 43, 23]
];

console.log(matrix.length); //4
js
// 循环输出二维数组每一项
for(let i = 0; i < 4; i++){
    for(let j = 0; j < 3; j++){
        console.log(matrix[i][j]);
    }
}

遍历数组的方法还包括:every()、filter()、forEach()、map()等。

注意:这几个方法不会修改原数组。有了这几种方法,就可以替代一些 for 循环了。下面依次来介绍。

forEach()

forEach() 这种遍历方法只支持 IE8 以上的浏览器。IE8 及以下的浏览器均不支持该方法。所以如果需要兼容 IE8,则不要使用 forEach,改为使用 for 循环来遍历即可。

forEach()方法需要一个函数作为参数。这种函数,是由我们创建但是不由我们调用的,我们称为回调函数。

数组中有几个元素,该回调函数就会执行几次。

回调函数中传递三个参数:

  • 第一个参数,就是当前正在遍历的元素

  • 第二个参数,就是当前正在遍历的元素的索引

  • 第三个参数,就是正在遍历的数组

forEach方法不返回值,只用来操作数据。

如果数组遍历的目的是为了改变数据得到返回值,那么使用map方法,否则使用forEach方法。

js
let arr = ["tian" , "黛玉" , "宝钗"];

arr.forEach(function(item , index , arr){
	console.log(item , index , arr);//一般不需要数组本身arr
})

//打印结果
tian 0 ["tian", "黛玉", "宝钗"]
黛玉 1 ["tian", "黛玉", "宝钗"]
宝钗 2 ["tian", "黛玉", "宝钗"]

小练习

弹出对应标签的内容

html
<ul>
    <li>001</li>
    <li>002</li>
    <li>003</li>
    <li>004</li>
    <li>005</li>
</ul>

<script>
    let aLi = document.querySelectorAll("ul li");

    aLi.forEach(function(item , index){
        console.log(item , index);
        item.onclick = function(){
            // alert(index);
            alert(this.innerHTML)//打印每一项的内容
        }
    })
// 除了数组forEach之外
// querySelectorAll获取的节点列表也可以forEach
</script>

map

map方法与forEach方法很相似,也是对数组的所有成员依次执行参数函数。

同样传递三个参数 该方法法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。

map方法将数组的所有成员依次执行参数函数,,然后把每一次的执行结果组成一个新数组返回。不会改变原数组。

举例 1:(拷贝的过程中改变数组元素的值)

一个已知的数组 arr1,我要求让 arr1 中的每个元素的值都乘 10,这里就可以用到 map 方法。代码举例:

js
let arr = [12, 23, 24, 42, 1];
let result = arr.map(function (item, index, arr) {
    return item * 10;
});
console.log(result); //[120,230,240,420,10];  原数组拷贝了一份,并进行了修改
console.log(arr);//[12,23,24,42,1];  原数组并未发生变化

举例 2:【重要案例,实际开发中经常用到】

将 A 数组中某个属性的值,存储到 B 数组中。代码举例:

js
let arr1 = [
    { name: "tian", age: "18" },
    { name: "夕颜", age: "16" },
];

//将数组 arr1 中的 name 属性,存储到 数组 arr2 中
let arr2 = arr1.map(function(item){
    return item.name;
});

// 将数组 arr1 中的 name、age这两个属性,改一下“键”的名字,存储到 arr3中
let arr3 = arr1.map(function (item) {
    return {
        myName: item.name,
        myAge: item.age,
    };
});

console.log(arr2);	// ["tian", "夕颜"]
console.log(arr3);	// [{"myName":"tian","myAge":"18"},{"myName":"夕颜","myAge":"16"}]

map 的应用场景,主要就是以上两种。

filter()

filter方法用于过滤数组成员,它的参数是一个函数.

对数组中的每一项运行回调函数返回结果为true的成员组成一个新数组返回,不会改变原数组

该方法法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。

语法:

js
arr.filter(function (item, index, arr) {
    return true;
});
js
let arr = [1 , 3 , 4, 6, 8, 28 ];

let newArr  = arr.filter(function(item){
   
    return item % 2 == 0;
    //return !(item % 2);
})

console.log(newArr);

//找出数组 arr1 中大于 4 的元素,返回一个新的数组。代码如下:
let newArr  = arr.filter(function(item){
    if (item > 4) {
        return true; // 将arr1中大于4的元素返回,组成新的数组
    }
    return false;

    //上方代码更简洁的写法如下:
     //return (item > 4);
})
console.log(newArr);

举例

获取数组 A 中指定类型的对象,放到数组 B 中。代码举例如下:

js
let arr = [
    { name: "许嵩", type: "一线" },
    { name: "周杰伦", type: "过气" },
    { name: "邓紫棋", type: "一线" },
];

let newArr = arr.filter((item) => item.type == "一线"); // 筛选出一线歌手

console.log(newArr);

打印结果:

js
[
    { name: '许嵩', type: '一线' },
    { name: '邓紫棋', type: '一线' },
];

every()

every():对数组中每一项运行回调函数,如果都返回 true,every 就返回 true;如果有一项返回 false,则停止遍历,此方法返回 false。

注意:every()方法的返回值是 boolean 值,参数是回调函数。

举例:

js
let arr1 = ["千古", "宿敌", "南山忆", "素颜"];
let bool1 = arr1.every(function (element, index, array) {
    if (element.length > 2) {
        return false;
    }
    return true;
});
console.log(bool1); //输出结果:false。只要有一个元素的长度是超过两个字符的,就返回false


let arr2 = ["千古", "宿敌", "南山", "素颜"];
let bool2 = arr2.every(function (element, index, array) {
    if (element.length > 2) {
        return false;
    }
    return true;
});
console.log(bool2); //输出结果:true。因为每个元素的长度都是两个字符。

some()

some():对数组中每一个元素运行回调函数,只要有一个元素返回 true,则停止遍历,此方法返回 true

注意:some()方法的返回值是 boolean 值。

every() 和 some() 的使用场景

every() 和 some() 这两个方法,初学者很容易搞混。要怎么区分呢?你可以这样记:

every():全部真,才为真。当你需要让数组中的每一个元素都满足指定条件时,那就使用 every()。

some():一个真,则为真,点到为止。数组中只要有一个元素满足指定条件时,就停止遍历。那就使用 some()。

find()

js
find(function(item, index, arr){
    return true;
});

作用:找出第一个满足「指定条件返回 true」的元素;如果没找到,则返回 undefined。

备注:一旦找到符合条件的第一个元素,将不再继续往下遍历。

举例:

js
let arr = [2, 3, 2, 5, 7, 6];

let result = arr.find(function(item, index,arr){
    return item > 4; //遍历数组arr,一旦发现有第一个元素大于4,就把这个元素返回
});

console.log(result); //打印结果:5

findIndex()

语法

findIndex(function(item, index, arr){
    return true;
});

作用:找出第一个满足「指定条件返回 true」的元素的 index。

举例:

我们直接把上面的代码中的 find 方法改成 findIndex,来看看效果。

js
let arr = [2, 3, 2, 5, 7, 6];

let result = arr.findIndex(function(item, index,arr){
    return item > 4; //遍历数组arr,一旦发现有第一个元素大于4,就把这个元素的index返回
});
console.log(result); //打印结果:3

应用

从我们获取的数据中筛选查找

js
let students = [
    { 
        name: "tian",
        sex: "", 
        age: 18 
    },
    {
        name: "夕颜",
        sex: "",
        age: 16,
    },
    {
        name: "张三",
        sex: "",
        age: 56,
    },
];

let femaleStu = students.find(function (item) {
    return item.sex === "";
});
let femaleStuIndex = students.findIndex(function (item) {
    return item.sex === "";
});

console.log(femaleStu); //{name: "夕颜", sex: "女", age: 16}
console.log(femaleStuIndex); //1

reduce()方法

reduce() 语法

reduce 的发音:[rɪ'djuːs]。中文含义是减少,但这个方法跟“减少”没有任何关系。

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。返回值是回调函数累计处理的结果。

语法

js
arr.reduce(function (previousValue, currentValue, currentIndex, arr) {},    initialValue);

//参数解释:
//previousValue:必填,上一次调用回调函数时的返回值

//currentValue:必填,当前正在处理的数组元素

//currentIndex:选填,当前正在处理的数组元素下标

//arr:选填,调用 reduce()方法的数组

//initialValue:选填,可选的初始值(作为第一次调用回调函数时传给 previousValue 的值)

在以往的数组方法中,匿名的回调函数里是传三个参数:item、index、arr。

但是在 reduce() 方法中,前面多传了一个参数previousValue

这个参数的意思是上一次调用回调函数时的返回值。第一次执行回调函数时,previousValue 没有值怎么办?可以用 initialValue 参数传给它。

备注:

绝大多数人在一开始接触 reduce() 的时候会很懵逼,但是没关系,有事没事多看几遍,自然就掌握

了。如果能熟练使用 reduce() 的用法,将能替代很多其他的数组方法,并逐渐走上进阶之路,领先于他人。

为了方便理解 reduce(),我们先来看看下面的简单代码,过渡一下:

js
let arr = ["tian", "夕颜","王二麻子"];

arr.reduce(function(prev , item , index){
    console.log(prev);
    console.log(item);
    return 88;
},0)
//0 tian
//88 夕颜
//88 王二麻子

//上面的代码中,由于return的是固定值,所以 prev 打印的也是固定值(只有初始值是 0,剩下的遍历中,都是打印 88)。

//不传递第二个参数 index是从1开始的,第一次的prev的值是数组的第一个值
let arr = ["tian", "夕颜", "王二麻子"];

arr.reduce(function (prev, item, index) {
    console.log(prev, item, index);  // tian 夕颜 1  88 "王二麻子" 2

    return 88;
});

现在来升级一下,

实际开发中,prev 的值往往是动态变化的,这便是 reduce()的精妙之处。我们来看几个例子就明白了。

reduce() 的常见应用

举例 1

计算数组中所有元素项的总和乘积。代码实现:

js
let arr = [1, 2, 3, 4];
// 数组求和
let sum = arr.reduce(function (prev,item) {
    return prev + item;
});
console.log(sum);// 打印结果:10
//数组求乘积
let mul = arr.reduce(function (prev,item) {
    return prev * item;
});
console.log(mul); // 打印结果:24

举例 2

**统计某个元素出现的次数。**代码实现:

js
let arr1 = [1, 2, 6, 5, 6, 1, 6];

function repeatCount(arr, value) {
    if (!arr || arr.length == 0) return 0;

    return arr.reduce((totalCount, item) => {
        totalCount += item == value ? 1 : 0;
        return totalCount;
    }, 0);
}

console.log(repeatCount(arr1, 6)); // 打印结果:3


//计算数组中每个元素出现的次数

let arr = [10, 2, 3, 4, 2, 10, 10];

let counts = arr.reduce(function (pre, item) {
    if (item in pre) {
        pre[item]++;
    } else {
        pre[item] = 1;
    }
    return pre;
}, {});

console.log(counts); //{2: 2, 3: 1, 4: 1, 10: 3}

举例 3

求元素的最大值:代码实现:

js
let arr = [2, 0, 1, 9, 6];
// 数组求最大值
let maxValue = arr.reduce((prev, item) => {
    return prev > item ? prev : item;
});

console.log(maxValue); // 打印结果:9

数组的方法清单

数组的类型相关

方法描述备注
Array.isArray()判断是否为数组
toString()将数组转换为字符串
Array.from(arrayLike)伪数组转化为真数组
Array.of(value1, value2, value3)创建数组:将一系列值转换成数组

注意,获取数组的长度是用length属性,不是方法。

数组元素的添加和删除

方法描述备注
push()向数组的最后面插入一个或多个元素,返回结果为新数组的长度会改变原数组
pop()删除数组中的最后一个元素,返回结果为被删除的元素会改变原数组
unshift()在数组最前面插入一个或多个元素,返回结果为新数组的长度会改变原数组
shift()删除数组中的第一个元素,返回结果为被删除的元素会改变原数组
slice()从数组中提取指定的一个或多个元素,返回结果为新的数组不会改变原数组
splice()从数组中删除指定的一个或多个元素,返回结果为被删除元素组成的新数组会改变原数组
fill()填充数组:用固定的值填充数组,返回结果为新的数组不会改变原数组

数组的合并和拆分

方法描述备注
concat()合并数组:连接两个或多个数组,返回结果为新的数组不会改变原数组
join()将数组转换为字符串,返回结果为转换后的字符串不会改变原数组
split()将字符串按照指定的分隔符,组装为数组不会改变原字符串

注意,split()是字符串的方法,不是数组的方法。

数组排序

方法描述备注
reverse()反转数组,返回结果为反转后的数组会改变原数组
sort()对数组的元素,默认按照Unicode 编码,从小到大进行排序会改变原数组

查找数组的元素

方法描述备注
indexOf(value)从前往后索引,检索一个数组中是否含有指定的元素
lastIndexOf(value)从后往前索引,检索一个数组中是否含有指定的元素
includes(item)数组中是否包含指定的内容
find(function())找出第一个满足「指定条件返回 true」的元素
findIndex(function())找出第一个满足「指定条件返回 true」的元素的 index
every()确保数组中的每个元素都满足「指定条件返回 true」,则停止遍历,此方法才返回 true全真才为真。要求每一项都返回 true,最终的结果才返回 true
some()数组中只要有一个元素满足「指定条件返回 true」,则停止遍历,此方法就返回 true一真即真。只要有一项返回 true,最终的结果就返回 true

遍历数组

方法描述备注
for 循环这个大家都懂
forEach()和 for 循环类似,但需要兼容 IE8 以上forEach() 没有返回值。也就是说,它的返回值是 undefined
map()对原数组中的每一项进行加工,将组成新的数组不会改变原数组
filter()过滤数组:返回结果是 true 的项,将组成新的数组,返回结果为新的数组不会改变原数组
reduce接收一个函数作为累加器,返回值是回调函数累计处理的结果

下面的数组方法改变了原来数组

arr.push() arr.unshift() arr.pop() arr.shift() arr.splice() arr.reverse() arr.sort()