内置对象简介
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);
数组的长度
数组的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
实际上是伪数组,并不是真实的数组:
既然btnArray
是伪数组,它就不能使用数组的一般方法,否则会报错:
解决办法:采用Array.from
方法将btnArray
这个伪数组转换为真数组即可:
js
Array.from(btnArray);
然后就可以使用数组的一般方法了:
3.数组的方法
数组的头尾操作方法
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);
//结果如下图
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()方法可以 使字符串转为数组。 不改变原字符串
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'));
// 同上
备注: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>
冒泡排序
实现原理
数组中有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()