数组
数组
数组 也是我们在开发中使用到的最多的数据结构之一,它本质上也是一个对象,但与对象不同的是,数组是一个有序的集合
创建数组
创建数组有两种方式:
- 直接创建(字面量)
let arr = [1, 2, 3]; console.log(arr); // [1, 2, 3]
- 使用构造函数创建
let arr = new Array(1, 2, 3); console.log(arr); // [1, 2, 3]
数组是有顺序的,它的索引从0开始(索引也被称为下标),一直到数组的最后一个元素结束(arr.length - 1
)
访问数组
访问或修改数组中的元素,可以通过数组的下标来操作,下标就是数组的索引
let arr = [1, 2, 3];
console.log(arr[0]); // 1
console.log(arr[1]); // 2
arr[2] = 4;
console.log(arr); // [1, 2, 4]
通过索引来访问数组元素的方式与访问对象属性的方式十分类似,数组的索引就相当于对象的 key
,而数组中的元素就相当于对象的 value
length 属性
length
属性表示数组的长度,即数组中元素的个数
let arr = [1, 2, 3];
console.log(arr.length); // 3
当我们修改数组的时候,数组的 length
属性会自动更新,数组的 length
属性是可写的,我们可以通过修改 length
属性的值来修改数组的长度
let arr = [1, 2, 3];
arr[5] = 6;
console.log(arr.length); // 6
console.log(arr); // [1, 2, 3, empty × 2, 6]
当数组的 length
属性被修改的时候,数组的长度会自动更新,如果修改后的 length
属性值小于原数组的长度,那么数组中多出的元素会被删除,所以清空一个数组最简单的方法就是将 length
属性的值设置为 0
let arr = [1, 2, 3];
arr.length = 2;
console.log(arr.length); // 2
console.log(arr); // [1, 2]
arr.length = 0;
console.log(arr.length); // 0
console.log(arr); // []
遍历数组
我们可以使用 for
循环遍历数组
for
循环遍历:使用for
循环遍历数组时需要设置合适的循环条件let arr = [1, 2, 3]; for (let i = 0; i < arr.length; i++) { console.log(arr[i]); } // 1 // 2 // 3
for...of
循环遍历:使用for...of
循环遍历数组时获取的是数组元素,无法获取数组元素的索引let arr = [1, 2, 3]; for (let item of arr) { console.log(item); } // 1 // 2 // 3
for...in
循环遍历:for...in
循环主要是用来遍历对象,但数组本质上也是对象,所以也可以使用for...in
循环,但是一般不建议这样使用,因为for...in
循环会遍历数组中的所有属性,包括数组的length
属性let arr = [1, 2, 3]; for (let key in arr) { console.log(arr[key]); } // 1 // 2 // 3
数组方法
数组 Array
为我们提供了许多内置的方法,这些方法都在 Array
的原型对象上,我们可以直接通过数组调用这些方法
push()
push()
方法用于向数组的末尾添加一个或多个元素,并返回修改后数组的长度
let arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]
console.log(arr.push(5)); // 5
console.log(arr); // [1, 2, 3, 4, 5]
pop()
pop()
方法用于删除数组的最后一个元素,并返回删除的元素
let arr = [1, 2, 3];
arr.pop();
console.log(arr); // [1, 2]
console.log(arr.pop()); // 2
console.log(arr); // [1]
shift()
shift()
方法用于删除数组的第一个元素,并返回删除的元素
let arr = [1, 2, 3];
arr.shift();
console.log(arr); // [2, 3]
console.log(arr.shift()); // 1
console.log(arr); // [3]
unshift()
unshift()
方法用于向数组的头部添加一个或多个元素,并返回修改后数组的长度
let arr = [1, 2, 3];
arr.unshift(0);
console.log(arr); // [0, 1, 2, 3]
console.log(arr.unshift(-1)); // 5
console.log(arr); // [-1, 0, 1, 2, 3]
splice()
splice()
方法用于删除、插入、替换数组的元素,并返回被删除、插入、替换的元素,他会改变原有数组。它接收3个参数,具体用法如下:
splice(start)
:删除从start
索引开始的元素splice(start, deleteCount)
:删除从start
索引开始的deleteCount
个元素splice(start, deleteCount, item1, item2, ...)
:删除从start
索引开始的deleteCount
个元素,并插入item1, item2, ...
元素
let arr = [1, 2, 3, 4, 5];
arr.splice(2); // 从索引为2开始删除所有元素
console.log(arr); // [1, 2]
arr.splice(2, 2, 6, 7); // 从索引为2开始删除2个元素,并插入6和7
console.log(arr); // [1, 2, 6, 7]
arr.splice(3,1); // 从索引为3的元素开始删除一个元素
console.log(arr); // [1, 2, 6, 7]
slice()
slice()
方法用于从数组中截取指定索引范围内的元素,并返回一个新的数组,slice
方法接收2个参数,具体用法如下:
slice(start)
:从start
索引开始截取到数组的末尾slice(start, end)
:从start
索引开始截取到end
索引结束
start
参数可以取负值,表示从数组的末尾开始计算索引,当 start
小于 0 时,start
参数的计算方式是 start + arr.length
,end
参数可以省略,当省略 end
参数时,end
参数的计算方式是 arr.length
let arr = [1, 2, 3, 4, 5];
let newArr = arr.slice(1, 3);
console.log(newArr); // [2, 3]
console.log(arr.slice(2)) // ==> slice(2, 5) [3, 4, 5]
console.log(arr.slice(2, 1)) // []
console.log(arr.slice(-1)) // ==> slice((-1 + 5), 5) [5]
concat()
concat()
方法用于将多个数组拼接成一个新数组,并返回拼接后的数组
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let newArr = arr1.concat(arr2);
console.log(newArr); // [1, 2, 3, 4, 5, 6]
join()
join()
方法用于将数组中的元素拼接成一个字符串,并返回拼接后的字符串,它接收一个指定的分隔符作为参数,会使用传入的分隔符对数组元素进行分隔, 默认使用 ,
作为分隔符
let arr = [1, 2, 3];
let str = arr.join();
console.log(str); // "1,2,3"
let str2 = arr.join('-');
console.log(str2); // "1-2-3"
reverse()
reverse()
方法用于将数组中的元素反转,并返回反转后的数组,此操作会改变原数组
let arr = [1, 2, 3];
arr.reverse();
console.log(arr); // [3, 2, 1]
sort()
sort()
方法用于对数组中的元素进行排序,并返回排序后的数组,它接收一个排序函数作为参数,根据排序函数的返回值对数组元素进行排序(默认排序是将元素转换为字符串,然后按照它们的 UTF-16 码元值升序排序),此操作会改变原数组
排序函数的返回值可以是以下几种情况:
- 如果返回值大于 0,则表示第一个元素应该排在第二个元素之后
- 如果返回值小于 0,则表示第一个元素应该排在第二个元素之前
- 如果返回值等于 0,则表示两个元素的位置不变
let arr = [3, 1, 2];
arr.sort();
console.log(arr); // [1, 2, 3]
arr.sort(function(a, b) {
return a - b;
});
console.log(arr); // [1, 2, 3]
arr.sort(function(a, b) {
return b - a;
});
console.log(arr); // [3, 2, 1]
map()
map()
方法用于对数组中的每个元素进行操作,并返回一个新的数组,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组),处理函数的返回值会作为新数组中的每个元素
let arr = [1, 2, 3];
let newArr = arr.map(function(item, index, array) {
return item * 2;
});
console.log(newArr); // [2, 4, 6]
filter()
filter()
方法用于对数组中的每个元素进行条件判断,并返回一个新的数组,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组),新数组中的元素都是满足处理函数条件的元素
let arr = [1, 2, 3, 4, 5];
let newArr = arr.filter(function(item) {
return item > 3;
});
console.log(newArr); // [4, 5]
every()
every()
方法用于对数组中的每个元素进行条件判断,并返回一个布尔值,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组),如果数组中的所有元素都满足处理函数的条件,则返回 true
,否则返回 false
let arr = [1, 2, 3, 4, 5];
let result = arr.every(function(item) {
return item > 0;
});
console.log(result); // true
some()
some()
方法用于对数组中的每个元素进行条件判断,并返回一个布尔值,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组),如果数组的所有元素中至少有一个元素满足处理函数的条件,则返回 true
,否则返回 false
let arr = [1, 2, 3, 4, 5];
let result = arr.some(function(item) {
return item > 3;
});
console.log(result); // true
reduce()
reduce()
方法用于对数组中的每个元素进行累加操作,并返回累加后的结果,它接收一个处理函数和一个初始值作为参数,它不会改变原数组,处理函数的参数包括:
accumulator
:上次累加的结果(在第一次调用时如果指定了初始值,则为初始值,否则为数组中第一个元素的)currentValue
:当前元素(在第一次调用时如果指定了初始值,则为数组中第一个元素,否则为数组中第二个元素)currentIndex
:currentValue 在数组中的索引(在第一次调用时如果指定了初始值,则为0,否则为1)array
:原数组
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce(function(accu, curr) {
return accu + curr;
});
console.log(result); // 15
forEach()
forEach()
方法用于对数组中的每个元素进行操作,但不返回任何结果,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组)
let arr = [1, 2, 3, 4, 5];
arr.forEach(function(item) {
console.log(item);
});
// 1
// 2
// 3
// 4
// 5
indexOf()
indexOf()
方法用于查找给定元素第一次出现在数组中的索引,如果查找到该元素,返回该元素的索引,否则返回 -1,它接收2个参数,具体用法如下:
indexOf(searchElement)
:查找给定元素第一次出现在数组中的索引indexOf(searchElement, fromIndex)
:查找给定元素第一次出现在数组中的索引,从fromIndex
索引开始查找
let arr = [1, 2, 3, 4, 5];
console.log(arr.indexOf(3)); // 2
console.log(arr.indexOf(4,3)) // 3
console.log(arr.indexOf(6)); // -1
lastIndexOf()
lastIndexOf()
方法与 indexOf()
方法类似,不同的是 lastIndexOf()
方法是从数组的最后一个元素开始查找指定元素的索引,并返回该元素的索引,如果数组中不存在该元素,则返回 -1
,它的参数与 indexOf()
方法相同
let arr = [1, 2, 3, 4, 5];
console.log(arr.lastIndexOf(3)); // 2
console.log(arr.indexOf(4,3)) // 3
console.log(arr.lastIndexOf(6)); // -1
find()
find()
方法用于查找数组中满足指定条件的第一个元素,并返回该元素的值,如果数组中不存在满足条件的元素,则返回 undefined
,它接收一个处理函数作为参数,处理函数的参数包括 currentValue
(当前元素)、index
(当前元素的索引)、array
(原数组)
let arr = [1, 2, 3, 4, 5];
console.log(arr.find(function(item) {
return item > 3;
})); // 4
findIndex()
findIndex()
方法与 find()
方法类似,不同的是 findIndex()
方法返回满足指定条件的第一个元素的索引,如果数组中不存在满足条件的元素,则返回 -1
let arr = [1, 2, 3, 4, 5];
console.log(arr.findIndex(function(item) {
return item > 3;
})); // 3
fill()
fill()
方法用于将数组中的所有元素填充为指定的值,并返回填充后的数组,他会改变原数组,它接收3个参数,具体用法如下:
fill(value)
:将数组中的所有元素填充为指定的值fill(value, start)
:从start
索引开始填充数组,如果start
小于 0,则start
参数的计算方式是start + arr.length
fill(value, start, end)
:从start
索引开始填充数组,到end
索引结束,如果start
小于 0,则start
参数的计算方式是start + arr.length
,如果end
小于 0,则end
参数的计算方式是end + arr.length
let arr = [1, 2, 3, 4, 5];
arr.fill(0);
console.log(arr); // [0, 0, 0, 0, 0]
arr.fill(1, 2);
console.log(arr); // [1, 1, 0, 0, 0]
arr.fill(2, 1, 3);
console.log(arr); // [1, 2, 2, 0, 0]
flat()
flat()
方法用于将嵌套的数组扁平化,即按照给定的展开层数将子数组中的元素添加到新数组中,它接收一个指定的展开层数作为参数,如果展开层数为 Infinity
,则表示将所有子数组中的元素添加到新数组中,并返回扁平化后的数组,它不会改变原数组
let arr = [1, 2, [3, 4], [5, [6, 7]]];
let newArr = arr.flat();
console.log(newArr); // [1, 2, 3, 4, 5, [6, 7]]
entries()
entries()
方法用于返回数组中每个元素的键值对,并返回一个迭代器对象,可以使用 for...of
循环遍历迭代器对象获取每个元素的键值对
let arr = ['a', 'b', 'c'];
let iterator = arr.entries();
for (let item of iterator) {
console.log(item); // ['0', 'a'] ['1', 'b'] ['2', 'c']
}
类数组
在 JavaScript 中,类数组(Array-like Object)是一种类似数组的对象,它具有一个 length 属性,并且可以通过索引访问元素,但是它没有数组的一些方法,例如 push()
、pop()
等,它通常是通过其他对象(例如 DOM 元素)的属性或方法来实现的。
常见的类数组对象有:
arguments
对象NodeList
对象HTMLCollection
对象字符串
Set
对象Map
对象
可以使用 Array.from()
方法将类数组对象转换为数组,或者使用 Array.prototype.slice.call()
方法将类数组对象转换为数组
let arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
let arr = Array.from(arrayLike);
console.log(arr); // ['a', 'b', 'c']
let arr2 = Array.prototype.slice.call(arrayLike);
console.log(arr2); // ['a', 'b', 'c']
数组去重
数组去重是前端开发中常见的需求,可以使用多种方法对数组进行去重操作。
Set
方法filter
方法map
方法reduce
方法indexOf
方法includes
方法Object
方法双重循环
方法
Set 方法
Set
方法是一种数据结构,它类似于数组,但是其中的元素都是唯一的,它可以用于对数组进行去重操作。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5]
filter 方法
filter
方法用于过滤数组中的元素,并返回一个新的数组,新数组中的元素都是满足指定条件的元素。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = arr.filter((item, index) => {
return arr.indexOf(item) === index;
});
console.log(uniqueArr); // [1, 2, 3, 4, 5]
map 方法
map
方法用于对数组中的每个元素进行操作,并返回一个新的数组,新数组中的元素都是处理函数的返回值。
let arr = [0, 1, 2, 3, 4, 5, 1, 2, 3, 6, 7];
let uniqueArr = arr.map((item, index,array) => {
return array.indexOf(item) === index ? item : undefined;
}).filter(item => item !== undefined)
console.log(uniqueArr); // [0, 1, 2, 3, 4, 5, 6, 7]
reduce 方法
reduce
方法用于对数组中的每个元素进行累加操作,并返回累加后的结果。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = arr.reduce((accu, item) => {
if (!accu.includes(item)) {
accu.push(item);
}
return accu;
}, []);
console.log(uniqueArr); // [1, 2, 3, 4, 5]
indexOf 方法
indexOf
方法用于查找给定元素第一次出现在数组中的索引,如果查找到该元素,返回该元素的索引,否则返回 -1。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = [];
for (let i = 0; i < arr.length; i++) {
if (uniqueArr.indexOf(arr[i]) === -1) {
uniqueArr.push(arr[i]);
}
}
console.log(uniqueArr); // [1, 2, 3, 4, 5]
includes 方法
includes
方法用于判断数组中是否包含给定的元素,如果包含该元素,则返回 true
,否则返回 false
。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = [];
for (let i = 0; i < arr.length; i++) {
if (!uniqueArr.includes(arr[i])) {
uniqueArr.push(arr[i]);
}
}
console.log(uniqueArr); // [1, 2, 3, 4, 5]
Object 方法
可以将不重复的数组元素保存在对象中,使用 Object.keys()
或者 Object.values()
方法来获取不重复的元素
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let obj = {};
for (let i = 0; i < arr.length; i++) {
if (!obj.hasOwnProperty(arr[i])) {
obj[arr[i]] = arr[i];
}
}
let uniqueArr = Object.values(obj)
console.log(uniqueArr); // [1, 2, 3, 4, 5]
双重循环
双重循环是一种比较低效的方法,它需要遍历数组中的每个元素,并判断该元素是否已经存在于新数组中。
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
let uniqueArr = [];
for (let i = 0; i < arr.length; i++) {
let isUnique = true;
for (let j = 0; j < uniqueArr.length; j++) {
if (arr[i] === uniqueArr[j]) {
isUnique = false;
break;
}
}
if (isUnique) {
uniqueArr.push(arr[i]);
}
}
console.log(uniqueArr); // [1, 2, 3, 4, 5]