数组的存储性能比普通对象要好
数组可以存储任何类型的元素
创建数组
//常规方式
var myCars=new Array();
myCars[0]="Saab";
myCars[1]="Volvo";
myCars[2]="BMW";
//简洁方式
var myCars=new Array("Saab","Volvo","BMW");
//字面量
var myCars=["Saab","Volvo","BMW"];
数组方法
添加删除
push、pop、unshift、shift
- 可以通过这几个方法用数组模拟栈、队列
- push、pop性能比unshift、shift好,因为移动元素量小
- push:可以一次在数组末尾添加多个元素,返回长度
- pop:返回被删除的元素
- unshift:可以一次在数组头部添加多个元素,返回长度
- shift:返回被删除的元素
slice
newArr = arr.slice(start, end);
- 提取 ,不改变arr,返回提取值
- slice(起始index【包括】,结束index【不包括】),包左不包括右
- 可以用
arr.slice()在对基本数据类型深拷贝,对引用数据类型浅拷贝
splice
newArr = arr.splice(start, deleteCount);
newArr = arr.splice(start, deleteCount, newItem1, newItem2...);
- 删除,改变数组,返回被删除的值
- splice(起始index【包括】,切除数量,插入数值【可以大于切除数量】)
- 相较于delete删除,产出后元素可以移动并且占据被释放的位置
arr.splice(2, 0, "complex", "language"),通过将deleteCount==0可以插入元素- 允许反向索引
let arr = [1, 2, 5];
// 从索引 -1(尾端前一位),删除 0 个元素,然后插入 3 和 4
arr.splice(-1, 0, 3, 4);
alert( arr ); // 1,2,3,4,5
合并拆分
concat
concat(需要连接的数组,需要连接的数组.,..,也可以变成要插入的数值,...,)
- 连接多个数组,不改变arr,返回连接结果
join
join(数组中元素连接符)
- 默认为“,”
- 即[a,b]=>'a,b'
- 将数组转变成字符串,不改变arr, 返回转变后的字符串
排序
sort
sort(fn)
- 排序,按照unicode 或者 fn 排序,改变arr
- 如果返回一个大于 0 的值,则元素会交换位置
- 如果返回一个小于 0 的值,则元素位置不变
- 如果返回一个等于 0 的值,则认为两个元素相等,则不交换位置
- 升序排列
sort(function(a,b){return a-b}) - 降序排列
sort(function(a,b){return b-a})
reverse
倒置,改变arr
查找
indexOf
arr.indexOf(item, from)
从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1。
lastIndexOf
arr.lastIndexOf(item, from)
从后往前遍历数组,从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1。
includes
arr.includes(item, from)
从索引 from 开始搜索 item,如果找到则返回 true(译注:如果没找到,则返回 false)。
可以正确处理NaN
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1(错,应该为 0)
alert( arr.includes(NaN) );// true(正确)
at
arr.at(i)
- 如果 i >= 0,则与 arr[i] 完全相同。
- 对于 i 为负数的情况,它则从数组的尾部向前数。
let fruits = ["Apple", "Orange", "Plum"];
// 与 fruits[fruits.length-1] 相同
alert( fruits.at(-1) ); // Plum
遍历
for循环
forEach
arr.forEach(function(self,index,arr){},this);
- self: 数组当前遍历的元素,默认从左往右依次获取数组元素。
- index: 数组当前元素的索引,第一个元素索引为0,依次类推。
- arr: 当前遍历的数组。
- this: 回调函数中this指向。
- 返回值为undefined
- 改变数组不稳定
-
- 数组元素是基本数据类型时,不改变arr
- 是引用数据类型时,整个修改元素对象,不改变arr
- 是引用数据类型时,修改对象某个属性,改变arr
// 1、数组的元素是基本数据类型
let numArr = [1, 2, 3];
numArr.forEach((item, index, arr) => {
arr[index] = arr[index] * 2;
});
console.log(JSON.stringify(numArr)); // 打印结果:[2,4,6]
// 2、数组的元素是引用数据类型时,直接修改对象
let objArr = [ { name: '千古壹号', age: 28 }, { name: '许嵩', age: 34 },];
objArr.forEach((item, index, arr) => {
arr[index] = {
name: '小明',
age: '10',
};
});
console.log(JSON.stringify(objArr)); // 打印结果:[{"name":"小明","age":"10"},{"name":"小明","age":"10"}]
// 3、数组的元素是引用数据类型时,修改对象的某个属性
let objArr2 = [ { name: '千古壹号', age: 28 }, { name: '许嵩', age: 34 },];
objArr2.forEach((item, index, arr) => {
arr[index].name = '小明';
});
console.log(JSON.stringify(objArr2)); // 打印结果:[{"name":"小明","age":28},{"name":"小明","age":34}]
for和foreach区别
- for与foreach都可以遍历数组/集合,不过for则在较复杂的循环中效率更高
- foreach不可以删除/修改集合元素,因为在使用foreach循环时数组就已经被锁定不能修改,否则会报出java.util.ConcurrentModificationException异常,而for可以,
- foreach和for都可以修改元素里面的属性
map
arr.map(function (item, index, arr) {return newItem });
- 对arr中的每一项进行加工,返回将组成新的数组
- map方法如果是修改整个item的值,则不会改变arr。但如果是修改 item 里面的某个属性,那就会改变arr。
- 返回值应为newArr的元素
const arr1 = [
{ name: '千古壹号', age: '28' },
{ name: '许嵩', age: '32' },
];
// 将数组 arr1 中的 name 属性,存储到 数组 arr2 中
const arr2 = arr1.map((item) => item.name);
// 将数组 arr1 中的 name、age这两个属性,改一下“键”的名字,存储到 arr3中
const arr3 = arr1.map((item) => ({
myName: item.name,
myAge: item.age,
})); // 将数组 arr1 中的 name 属性,存储到 数组 arr2 中
console.log('arr1:' + JSON.stringify(arr1));
console.log('arr2:' + JSON.stringify(arr2));
console.log('arr3:' + JSON.stringify(arr3));
arr1:[{"name":"千古壹号","age":"28"},{"name":"许嵩","age":"32"}]
arr2:["千古壹号","许嵩"]
arr3:[{"myName":"千古壹号","myAge":"28"},{"myName":"许嵩","myAge":"32"}]
filter
- 过滤数组:返回结果是 true 的项,将组成新的数组,返回结果为新的数组,不改变arr
find
- 找到数组中第一个返回值是true的项,如果没有则返回undefined,对空数组不执行,不改变arr
some
- 找到符合条件的项返回true,无则返回false,对空数组不执行,不改变arr
every
- 检测每一项元素是否都符合条件,都符合返回true,有不符合则返回false,对空数组不执行,不改变arr
reduce
arr.reduce(function (previousValue, currentValue, currentIndex, arr) {}, initialValue);
- previousValue:必填,上一次调用回调函数时的返回值
- currentValue:必填,当前正在处理的数组元素
- currentIndex:选填,当前正在处理的数组元素下标
- arr:选填,调用 reduce()方法的数组
- initialValue:选填,可选的初始值(作为第一次调用回调函数时传给 previousValue 的值)
- 对于
初始值执行三次,无初始值执行两次
const arr = [2, 0, 1, 9, 6];
const total = arr.reduce((prev, item) => {
return prev + item;
});
const arr = [2, 0, 1, 9, 6];
arr.reduce((prev, item) => {
if (prev.indexOf(item) == -1){
prev.push(item)
}
return prev;
},[]);
const arr = [{x:2},{x:5},{x:7}];
const total = arr.reduce((prev, item) => {
return prev + item.x;
});
const arr = [[2, 0, 1], [9, 6]];
arr.reduce((prev, item) => {
return prev.concat(item);
});
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 arr1 = [1, 2, 6, 5, 6, 1, 6];
arr.reduce((prev, item) => {
if(item in prev){//不用prev.item因为会把item变量固定为一个特定的参数
prev[item]++; //不用prev.item因为会把item变量固定为一个特定的参数
}else{
prev[item] = 1
}
return prev
},{});//记得传入空对象为初始值
/*错误案例
arr.reduce((prev, item) => {
if(prev.item){
prev.item++;
}else{
prev.item = 1
}
return prev
});
*/
const arr = [2, 0, 1, 9, 6];
const maxValue = arr.reduce((prev, item) => {
return prev > item ? prev : item;
});
console.log(maxValue); // 打印结果:9
var people =[( name: 'Alice', age: 21 ),( name: 'Max', age: 20 )},( name: 'Jane', age: 20 }];
function fn ( arr , key){
return arr.reduce((a,b)=>{
let temp = b[key]
//初始化数组
if (!a[temp]){a[temp] = []}
a[temp].push(b)
return a
},{})
}
fn ( people , age)
检查判断
Array.isArray
- 判断参数是否是array类型
创建数组
Array.from
作用:将伪数组或可遍历对象转换为真数组。
Array.of
Array.of(value1, value2, value3);
作用:根据参数里的内容,创建数组。
创建新方法
Array.prototype.myUcase=function(){
for (i=0;i<this.length;i++){
this[i]=this[i].toUpperCase();
}
}
数组属性
length
- 设置或返回数组元素的个数。
- 可写
- 清空数组最简单的方法就是
arr.length = 0
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // 截断到只剩 2 个元素
alert( arr ); // [1, 2]
arr.length = 5; // 又把 length 加回来
alert( arr[3] ); // undefined:被截断的那些数值并没有回来