这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
数组的方法有很多,在面试的过程中也遇到了非常多。不仅仅是数组方法的使用,如果想真正了解并掌握数组的各种方法,我们也可以通过实现它来加深记忆。
一、类数组转换为数组
什么是类数组?
- 类数组就是类似数组,它具有数组的length属性,但是不具有数组原型上的方法。
常见的类数组有:arguments、DOM操作返回的结果(比如document.getElementsByTagName())
那么很多时候,我们需要将类数组转换成数组,方便我们使用数组原型上的方法。
如何将类数组转换成数组?
下面是转换的几种方法:
1、Array.from
let newArr1 = Array.from(classArr);
2、Array.prototype.slice.call()
let newArr2 = Array.prototype.slice.call(classArr);
3、扩展运算符
let newArr3 = [...classArr];
4、利用concat拼接数组
let newArr4 = Array.prototype.concat.apply([], classArr)
以上这四种方法是最常见也是最实用的转换方法了。
二、手写filter()
filter()的用法
filter顾名思义,就是过滤,能过够过滤出数组当中符合条件的元素。注意:filter不会改变原数组
1、比如我们可以利用filter过滤出数组当中所有的偶数
let arr = [56, 15, 48, 3, 7];
let newArr = arr.filter(function(value, index, array) {
return value % 2 === 0;
});
console.log(newArr); // [56,48]
2、又或者利用filter来实现数组去重
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
实现filter()
首先看filter的语法:
array.filter(function(currentValue,index,arr), thisValue)
参数:
currentValue: 必选,当前元素的值index: 可选,当前元素的索引值arr: 可选,当前元素属于的数组对象thisValue: 可选,对象作为该执行回调时使用,传递给函数,作为this的值
下面是具体的实现方法:
Array.prototype.filter = function(callback, thisArg) {
if (this == undefined) {
throw new TypeError('this is null or not undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
const res = [];
// 让O成为回调函数的对象传递(强制转换对象)
const O = Object(this);
// >>>0 保证len为number,且为正整数
const len = O.length >>> 0;
for (let i = 0; i < len; i++) {
// 检查i是否在O的属性(会检查原型链)
if (i in O) {
// 回调函数调用传参
if (callback.call(thisArg, O[i], i, O)) {
res.push(O[i]);
}
}
}
return res;
}
三、手写forEach()
forEach()的用法
forEach()方法用于调用数组的每个元素,并将元素传递给回调函数。主要功能就是遍历数组,这个语句需要一个回调函数作为参数。注意:forEach返回值为undefined。
比如通过forEach()遍历数组并打印元素的值:
var arr = ['a', 'b', 'c'];
arr.forEach(function(value, index, arr) {
console.log(value); // a b c
})
实现forEach()
首先看forEach()的语法:
array.forEach(function(currentValue, index, arr), thisValue)
currentValue: 必选,当前元素的值index: 可选,当前元素的索引值arr: 可选,当前元素属于的数组对象thisValue: 可选,传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
下面是具体的实现方法:
Array.prototype.forEach = function(callback, thisArg) {
if (this == null) {
throw new TypeError("this is null or not defined");
}
if (typeof callback !== 'function') {
throw new TypeError(callback + "is not a function")
}
const O = Object(this);
const len = O.length >>> 0;
let k = 0;
while (k < len) {
if (k in O) {
callback.call(thisArg, O[k], k, O);
}
k++;
}
}
四、手写map()
map()的用法
map()方法也是对数组进行一系列的处理。并且返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。注意: map()不会改变原数组。
1、比如,我们想返回一个数组,数组中元素为原始数组的平方根。可以这么实现:
var nums = [4, 9, 16, 25];
function fn(nums) {
return nums.map(Math.sqrt)
}
console.log(fn(nums)); // [2, 3, 4, 5]
2、又或者数组中的每个元素都乘以输入框指定的值,并返回新数组
var nums = [4, 9, 16, 25];
function fn2() {
return nums.map(function(item, index, arr) {
// return num * document.getElementById("multiplyWith").value;
return item * 2
})
}
console.log(fn2(nums)); // [8, 18, 32, 50]
实现map()
首先来看一下map()的语法:
array.map(function(currentValue,index,arr), thisValue)
currentValue: 必选,当前元素的值index: 可选,当前元素的索引值arr: 可选,当前元素属于的数组对象thisValue: 可选,对象作为该执行回调时使用,传递给函数,作为this的值
下面是具体的实现方法:
Array.prototype.map = function(callback, thisArg) {
if (this === undefined) {
throw new TypeError("this is null or not defined");
}
if (typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function')
}
const res = [];
// 让O成为回调函数的对象传递(强制转换对象)
const O = Object(this);
// >>>0 保证len为number,且为正整数
const len = O.length >>> 0;
for (let i = 0; i < len; i++) {
// 检查i是否在O的属性(会检查原型链)
if (i in O) {
// 调用回调函数并传入新数组
res[i] = callback.call(thisArg, O[i], i, this)
}
}
return res;
}
五、手写reduce()
reduce()的用法
reduce()方法用于将数组元素计算为一个值(从左到右)。这个方法接收一个函数作为累加器,最终计算成最终的值。
比如计算数组元素四舍五入的总和:
var nums = [1, 2, 3]
function getSum(total, num) {
return total + Math.round(num)
}
function fn(item) {
return nums.reduce(getSum, 0)
}
console.log(fn(nums)); // 6
实现reduce()
先来看看它的语法:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
currentValue: 必选,当前元素的值index: 可选,当前元素的索引值arr: 可选,当前元素属于的数组对象thisValue: 可选,传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
下面是具体的实现方法:
Array.prototype.reduce = functon((callback, initialValue) {
if (this === undefined) {
throw new TypeError('this is null or not defined')
}
if (typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function')
}
const O = Object(this);
const len = O.length >>> 0;
let accumulator = initialValue; // 累加器
let k = 0;
// 如果第二个参数为undefined的情况下
// 则数组的第一个有效值作为累加器的初始值
if (accumulator === undefined) {
while (k < len && !(k in O)) {
k++;
}
// 如果超出数组界限还没有找到累加器的初始值,则抛出错误
if (k >= len) {
throw new TypeError("Reduce of empty array with no initial value")
}
accumulator = O[k++]
}
while (k < len) {
if (k in O) {
accumulator = callback.call(undefined, accumulator, O[k], k, O)
}
k++;
}
return accumulator;
})
总结
数组当中常用的方法大概就是这样,不管是在面试当中,还是实际开发当中,数组方法都是常见的,多思考多实践有助于加深记忆。