本文汇总了数组常用的方法。
因为[]
是Array
构造函数的实例对象,所以[]
可以访问到Array.prototype
上面的方法。
详情查看 MDN
push() / unshift()
:::info
作用:push() 会在数组的末尾新增数据
返回值:该方法返回新增数据后数组的新长度。
是否更改原数组:☑️
:::
var arr = [2, 3, 4];
arr.push(5);
var res = arr.push(6, 7, 8);
console.log(arr); // [2, 3, 4, 5, 6, 7, 8]
console.log(res); // 7
:::info
作用:unshift() 会在数组的开头新增数据
返回值:该方法返回新增数据后数组的新长度。
是否更改原数组:☑️
:::
var arr = [2, 3, 4];
arr.unshift(1);
var res = arr.unshift(11, 12);
console.log(arr); // [11, 12, 1, 2, 3, 4]
console.log(res); // 6
自己实现一个push()
方法:
Array.prototype.myPush = function () {
for (let index = 0; index < arguments.length; index++) {
// this 代表 arr
// arr[arr.length] 表示数组的长度,也就是最后一位
this[this.length] = arguments[index];
}
return this.length;
};
var arr = [];
var res = arr.myPush(1, 2, 3);
console.log(res, arr); // 3 [1, 2, 3]
pop() / shift()
:::info
作用:pop() 会从数组的末尾删除一个数据
返回值:该方法返回被删除的数据。
是否更改原数组:☑️
:::
var arr = ["a", "b", "c"];
var res = arr.pop();
console.log(res, arr); // c , ['a', 'b']
:::info
作用:shift() 会从数组的开头删除一个数据
返回值:该方法返回被删除的数据。
是否更改原数组:☑️
:::
var arr = ["a", "b", "c"];
var res = arr.shift();
console.log(res, arr); // a , ['b', 'c']
splice()
:::info
作用:该方法可用于新增、替换、删除数据元素
arr.splice(元素开始的下标,要删除元素的个数,要替换的元素)
返回值:该方法返回被删除元素后组成的数组,如果没有删除元素则返回空数组
是否更改原数组:☑️
:::
// 新增
var arr = ["a", "b", "c"];
var res = arr.splice(3, 0, "d");
console.log(arr); // ['a', 'b', 'c', 'd']
console.log(res); // []
// 新增多个数据
var arr = ["a", "b", "c"];
var res = arr.splice(3, 0, "d", "e", "f");
console.log(arr); // ['a', 'b', 'c', 'd', 'e', 'f']
console.log(res); // []
// 替换
var arr = ["a", "b", "c"];
var res = arr.splice(1, 1, "edit");
console.log(arr); // ['a', 'edit', 'c']
console.log(res); // ['b']
// 替换多个元素
var arr = ["a", "b", "c"];
var res = arr.splice(1, 2, "edit");
console.log(arr); // ['a', 'edit']
console.log(res); // ['b', 'c']
// 删除
var arr = ["a", "b", "c"];
var res = arr.splice(0, 2);
console.log(arr); // ['c']
console.log(res); // ['a', 'b']
这个数组的第0位参数还可以是负数,如果是负数,下标就会从数组的末尾往左数:
var arr = ["a", "b", "c"];
arr.splice(-1, 0, "d");
console.log(arr); // ['a', 'b', 'd', 'c']
reverse()
:::info
作用:该方法用于把数组进行反转。
返回值:该方法返回反转后的数组。
是否更改原数组:☑️
:::
var arr = [1, 2, 3];
var res = arr.reverse();
console.log(arr); // [3, 2, 1]
console.log(res); // [3, 2, 1]
sort()
:::info
作用:该方法用于把数组按照 ASCII 码表中的位置进行排序。
返回值:该方法返回排序后的数组。
是否更改原数组:☑️
:::
var arr = [-1, -5, 8, 0, 2];
var res = arr.sort();
console.log(arr); // [-1, -5, 0, 2, 8]
console.log(res); // [-1, -5, 0, 2, 8]
var arr = ["b", "z", "h", "i", "a"];
var res = arr.sort();
console.log(arr, res); // ['a', 'b', 'h', 'i', 'z']
// 按照 ASCII 码表进行比较
var arr = [27, 49, 5, 7]; // 先比较第一位
console.log(arr.sort()); // [27, 49, 5, 7]
我们还可以自定义排序规则。
sort()
方法还容许接收一个函数作为参数,该函数有以下三点需要注意
- 该函数必须有两个参数,我们姑且命名为
a
和b
- 函数必须有返回值
- 返回值应为任意的「正数」或「负数」
- 当
return
为「负数」时,a
排在前面- 当
return
为「正数」时,b
排在前面
var arr = [27, 49, 5, 7];
var res = arr.sort(function(a,b){
if(a < b){
return -1;
}else{
return 1;
}
// 可以简化成
// 假设 a 是 27,b 是 49,那么 27 - 49 = -22; 返回负数
return a - b;
});
console.log(arr); // [5, 7, 27, 49]
console.log(res); // [5, 7, 27, 49]
// =========
var arr = [27, 49, 5, 7];
var res = arr.sort(function(a,b){
return b - a;
});
console.log(arr); // [49, 27, 7, 5]
console.log(res); // [49, 27, 7, 5]
sort()
方法内部的原理其实就是「冒泡排序」的原理,sort()
方法执行的时候会一直循环,根据返回的是「正数」还是「负数」决定a
或者b
排在前面。 27 49 5 7 // 初始状态 27 49 5 7 // 拿 27 进行对比 27 5 7 49 // 拿 49 进行对比 5 27 7 49 // 拿 5 进行对比 5 7 27 49 // 拿 7 进行对比
既然知道了sort()
方法内部的原理,那么我们来实现几个实例吧。
随机排序
var arr = [1, 2, 3, 4, 5, 6];
arr.sort(function (a, b) {
// Math.random() 返回 0-1 之间的小数
// var rand = Math.random();
// 减去 0.5 后大于 0 表示 rand 肯定是 大于 0.5
// return rand - 0.5 > 0 ? 1 : -1;
// 简化
return Math.random() - 0.5;
});
console.log(arr);
数组对象排序
var arr = [
{ son: "Jenny", age: 18 },
{ son: "Jone", age: 10 },
{ son: "Ben", age: 16 },
{ son: "Crytal", age: 3 },
{ son: "Lucy", age: 11 },
];
arr.sort(function (a, b) {
return a.age - b.age;
});
console.log(arr);
// [{son: 'Crytal', age: 3}
// {son: 'Jone', age: 10}
// {son: 'Lucy', age: 11}
// {son: 'Ben', age: 16}
// {son: 'Jenny', age: 18}]
根据字符串长度排序
var arr = ["12345", "1", "1234", "12", "1234567"];
arr.sort(function (a, b) {
return a.length - b.length;
});
console.log(arr)
—-
concat()
作用:拼接数组 返回值:返回拼接的新数组
var arr1 = ["a", "b", "c"];
var arr2 = ["d", "e", "f"];
var arr3 = arr1.concat(arr2);
console.log(arr3, arr1, arr2);
// ["a", "b", "c", "d", "e", "f"]
// ["a", "b", "c"]
// ["d", "e", "f"]
slice()
作用:截取数组 返回值:返回截取的数组 参数:
- 参数1,开始截取位置的下标,如果没有参数则从0截取到数组的最后
- 参数2,结束截取位置的下标之前,如果只有参数 1 那么会从参数1的位置截取到最后
var arr = ["a", "b", "c", "d", "e", "f"];
var arr1 = arr.slice();
console.log(arr.slice(1, 3)); // ["b", "c"]
toString()
作用:将数组转换为字符串 返回值:返回转化的字符串
var arr = ["a", "b", "c", "d"];
console.log(arr.toString()); // a,b,c,d
join()
作用:将数组根据指定的字符转换成字符串 返回值:返回转化的字符串
var arr = ["a", "b", "c", "d"];
var str1 = arr.join(); // a,b,c,d 等于 arr.toString()
var str2 = arr.join("-"); // a-b-c-d
另外String.prototype
还有个split()
方法和join()
方法是对应的,split()
方法是将字符串按照指定的字符转换为数组
var arr = ["a", "b", "c", "d"];
var str2 = arr.join("-"); // a-b-c-d
var arr1 = str2.split("-"); // ["a", "b", "c", "d"];
indexOf()
说明:查找数组中是否存在某个值 参数1: 要查询的值 参数2: 开始查询的位置 返回:如果存在要查询的值返回这个值在数组中的下标,否则返回 -1 表示不存在
const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison')); // 1
console.log(beasts.indexOf('bison', 2)); // 4
console.log(beasts.indexOf('giraffe')); // -1
isArray
说明:判断参数是不是一个数组(这是一个静态方法) 返回:布尔值
Array.isArray([1, 2, 3]); // true
Array.isArray(new Array()); // true
Array.isArray(new Array('a', 'b', 'c', 'd')); // // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar'); // false
Array.isArray(undefined); // false
—-
forEach()
:::warning
说明:遍历数组
参数1:fn
每次遍历要执行的函数fn(当前遍历的元素, 当前遍历的元素下标, 当前遍历的数组)
参数2:每次执行fn
内的this
对象(默认指向window
对象)null
、undefind
的时候this
仍然指向window
对象,1
、"1"
、true/false
的时候this
指向相应的包装对象
返回值:无
:::
var data = [{ a: 1 }, { b: 2 }, { c: 3 }, { d: 4 }, { e: 5 }, { f: 6 }];
data.forEach(function(el, index, array){
console.log(el, index, array, this);
});
// {a: 1} 0 [{a: 1} ...] window
data.forEach(function(el, index, array){
console.log(el, index, array, this);
},{test: "test"});
// {a: 1} 0 [{a: 1} ...] {test: "test"}
模拟重写forEach()
方法:
Array.prototype.myForEach = function (fn) {
var array = this,
len = array.length,
arg2 = arguments[1] || this;
for (let i = 0; i < len; i++) {
// 每次遍历执行方法,然后更改 this 指向
fn.apply(arg2, [array[i], i, array]);
}
};
data.myForEach(function (el, index, array) {
console.log(el, index, array, this);
}, {});
filter()
:::warning
说明:过滤数组
参数1:fn
每次遍历要执行的函数fn
需返回一个布尔值表示是否要将遍历项返回出去
参数2:每次执行fn
内的this
对象(默认指向window
对象)
返回值:返回过滤后的新数组
:::
var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
var result = data.filter(function(el,index,array){
// 如果不指定 this,这里的 this 仍然指向 window
return el.id % 2 === 0
});
console.log(result); // [{ id: 2 }, { id: 4 }]
模拟重写filter()
方法:
Array.prototype.myFilter = function (fn) {
var arr = this,
len = arr.length,
arg2 = arguments[1],
newArr = [];
for (let i = 0; i < len; i++) {
var result = fn.apply(arg2, [arr[i], i, arr]);
result ? newArr.push(arr[i]) : "";
}
return newArr;
};
data.myFilter(function (el, index, array) {
return el.id % 2 === 0
}, {});
map()
:::warning
说明:创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
参数1:fn
每次遍历要执行的函数fn
需提供返回值
参数2:每次执行fn
内的this
对象(默认指向window
对象)
返回值:返回一个由返回值组成的新数组
:::
var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
var result = data.map(function (el, index, array) {
return el.id;
});
console.log(result); // [1, 2, 3, 4, 5, 6]
模拟重写map()
方法:
Array.prototype.myMap = function (fn) {
var arr = this,
len = arr.length,
arg2 = arguments[1],
newArr = [];
for (var i = 0; i < len; i++) {
var result = fn.apply(arg2, [arr[i], i, arr]);
// 将回调函数的返回值 push 到一个新的数组里
newArr.push(result);
}
return newArr;
};
var result = data.myMap(function (el, index, array) {
return el.id;
});
console.log(result);
every()
:::warning
说明:检查数组中的每一项是否符合return
的条件
参数1:fn
每次遍历要执行的函数fn
需提供返回值
参数2:每次执行fn
内的this
对象(默认指向window
对象)
返回值:布尔值
:::
var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
var result1 = data.every(function (el, index, array) {
return el.id;
});
var result2 = data.every(function (el, index, array) {
return el.name;
});
console.log(result1, result2); // true false
模拟重写every()
方法:
Array.prototype.myEvery = function (fn) {
var arr = this,
len = arr.length,
arg2 = arguments[1],
result = true;
for (var i = 0; i < len; i++) {
var bool = fn.apply(arg2, [arr[i], i, arr]);
// 如果有回调函数有一次返回 false,那就中止循环
if (!bool) {
result = false;
break;
}
}
return result;
};
var res = data.myEvery(function (el, index, array) {
return el.is_free === "0";
});
console.log(res);
some()
:::warning
说明:检查数组中的任意一项是否符合return
的条件(和every
相反)
参数1:fn
每次遍历要执行的函数fn
需提供返回值
参数2:每次执行fn
内的this
对象(默认指向window
对象)
返回值:布尔值
:::
var data = [
{ id: 1 },
{ id: 2 },
{ id: 3, name: "test" },
{ id: 4 },
{ id: 5 },
{ id: 6 },
];
var result1 = data.some(function (el, index, array) {
return el.id;
});
var result2 = data.some(function (el, index, array) {
return el.name;
});
console.log(result1, result2); // true true
模拟重写some()
方法:
Array.prototype.mySome = function (fn) {
var arr = this,
len = arr.length,
arg2 = arguments[1],
result = false;
for (var i = 0; i < len; i++) {
var bool = fn.apply(arg2, [arr[i], i, arr]);
// 如果回调函数有一项返回 true 那就中止循环
if (bool) {
result = true;
break;
}
}
return result;
};
var res = data.mySome(function (el, index, array) {
return el.is_free === "1";
});
console.log(res);
reduce()
:::warning
说明:迭代函数。每一次遍历会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
参数1:fn
每次遍历要执行的函数fn(前一次遍历处理后的数据, 当前遍历项, 当前遍历项的下标, 当前遍历的数组)
需返回一个处理后的数据
参数2:初始化数据
返回值:返回每次遍历迭代处理的数据
:::
var data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
];
var result1 = data.reduce(function (prev, el, index, array) {
console.log(prev);
prev.push(el.id);
return prev;
}, []);
console.log(result1);
// []
// [1]
// [1, 2]
// [1, 2, 3]
// [1, 2, 3, 4]
// [1, 2, 3, 4, 5]
// [1, 2, 3, 4, 5, 6]
var data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
];
var result1 = data.reduce(function (prev, el, index, array) {
console.log(prev)
prev += el.id;
return prev;
}, 0);
console.log(result1);
// 0
// 1
// 3
// 6
// 10
// 15
// 21
模拟重写reduce()
方法:
Array.prototype.myReduce = function (fn, initalVal) {
var arr = this,
len = arr.length;
for (let i = 0; i < len; i++) {
// 将返回值直接赋值给 initalVal
initalVal = fn(arg2, [initalVal, arr[i], i, arr]);
}
return initalVal;
};
data.myReduce(function(prev, el, index, array){
prev+= el.id;
return prev;
})
reduceRight()
:::warning
说明:和reduce()
函数是一样的,只不过是从数组的末尾遍历(倒序)
参数1:fn
每次遍历要执行的函数fn(前一次遍历处理后的数据, 当前遍历项, 当前遍历项的下标, 当前遍历的数组)
需返回一个处理后的数据
参数2:初始化数据
返回值:返回每次遍历迭代处理的数据
:::
var data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
];
var result1 = data.reduceRight(function (prev, el, index, array) {
console.log(el)
prev += el.id;
return prev;
}, 0);
console.log(result1);
// {id: 6}
// {id: 5}
// {id: 4}
// {id: 3}
// {id: 2}
// {id: 1}
// 21