前端面试基础-数组(Array)的常用方法总结

244 阅读10分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

得不得奖的无所谓希望能强迫自己闯一关╮( ̄▽ ̄)╭,上次更文未通关,这次继续

前言

记录常用 Array 方法的学习总结,梳理一些笔者可能比较容易忘的数组的api
有误请多多指正,附上女神图保命 [手动狗头]
学习已完成

  • 1. 循环的数组遍历的方法参考Array.prototype.forEach()、.map()、.filter()、.some()、.every()、.reduce()、.reduceRight() - 遍历
  • 2.Array.prototype.find、findIndex、indexOf、includes - 查找
  • 3.Array.prototype.flat - 扁平化
  • 4.Array.from 与 ES6 的(扩展运算符 ...) - 数组转换
  • 5.Array.prototype.keys、.values、.entries - 键值
  • 6.Array.prototype.push、unishift、shift、pop - 堆栈
  • 7.Array.prototype.reverse 与 sort - 排序
  • 8.Array.prototype.concat、join 与 split - 合并拆分
  • 9.Array.prototype.fill、copyWithin、slice、splice - 填充、数组内部浅拷贝、原数组的部分浅拷贝、替换修改数组部分元素
  • 10.Array.of、Array.isArray - 其他方法

1 循环的数组遍历的方法参考

之前的文章# JS中的12种遍历方法

2.Array.prototype.find、findIndex、indexOf、includes - 查找

通常用于判断值在不在,找索引或该索引的值

find()  方法返回数组中满足提供的测试函数的第一个元素的值****。否则返回 [undefined]
findIndex() 方法返回数组中满足提供的测试函数的
第一个元素的索引**。若没有找到对应元素则返回-1。

PS: 注意以上方法均不作类型检测

const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > '5');
console.log(found); // 12
const foundIndex = array1.findIndex(element => element > '5');
console.log(foundIndex); // 1

indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
该方法存在类型校验,如下 '5' 会返回-1,5 则会返回 0
includes()  方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false

PS: 注意以上方法均存在类型检测

const array1 = [5, 12, 8, 130, 44];
const indexOftest = array1.indexOf('5');
const indexOftest2 = array1.indexOf(5);
console.log(indexOftest, indexOftest2); // -1 0
const includesTest = array1.includes('5');
const includesTest2 = array1.includes(5);
console.log(includesTest, includesTest2); // false true

3.Array.prototype.flat - 扁平化

flat()  方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。 常用于多层嵌套数组扁平化

/*
    Array - arr.flat([depth]) 扁平化多维数组
    1. 可选参数:depth  指定要提取嵌套数组的结构深度,默认值为 1。
    2. 返回值:一个包含将数组与子数组中所有元素的新数组
    3. Infinity 无限扁平
*/
function flatArray() {
    const arr1 = [0, 1, 2, [3, 4]];
    // 默认会递归处理一层数组
    console.log(arr1.flat()); // [0, 1, 2, 3, 4]
    const arr2 = [0, 1, 2, [ [ [3, 4] ] ]];
    // 接收参数是指定要提取嵌套数组的结构深度,默认值为 1。
    console.log(arr2.flat(2)); // [0, 1, 2, [3, 4]]
    let arr = [[1,2],[3,4],[[6,7],[[8],[9,10]]]];
    let el = arr.flat(Infinity);
    console.log(el);  // [1, 2, 3, 4, 6, 7, 8, 9, 10];
}
flatArray()

自定义扁平化

let arr = [[1,2],[3,4],[[6,7],[[8],[9,10]]]];
let newArr = []
function customFlat(arr){
    arr.forEach(e=>{
        if(Array.isArray(e)){
            customFlat(e)
        }else{
            newArr.push(e)
        }
    })
   return newArr;
}
console.log(customFlat(arr))

4.Array.from 与 ES6 的(扩展运算符 ...) - 数组转换

Array.from()  方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

function toArray(arr,){
    console.log(Array.from('foo'));
    // expected output: Array ["f", "o", "o"]
    console.log(Array.from([1, 2, 3], x => x + x));
    // expected output: Array [2, 4, 6]
    console.log('arguments: ', arguments); // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
    console.log('arguments typeof: ',typeof arguments); // object
    console.log(Array.from(arguments)) // [ 1, 2, 3, 4, 5 ]

    // 扩展运算符
    console.log([...arguments]) // [ 1, 2, 3, 4, 5 ]
}
toArray(1,2,3,4,5)

5.Array.prototype.keys、.values、.entries - 键值

keys() 方法返回一个包含数组中每个索引键的 Array Iterator 对象。

const array1 = ['a', 'b', 'c'];
const iterator = array1.keys();
for (const key of iterator) {
  console.log(key); // 0 1 2
}

values()  方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值

const array1 = ['a', 'b', 'c'];
const iterator = array1.values();
for (const value of iterator) {
  console.log(value); // a b c
}

entries()  方法返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键/值对。

一个新的 Array 迭代器对象。Array Iterator 是对象,它的原型(proto:Array Iterator)上有一个 next 方法,可用用于遍历迭代器取得原数组的[key,value]

const array1 = ['a', 'b', 'c'];
const iterator1 = array1.entries();
console.log(iterator1.next().value); // Array [0, "a"]
console.log(iterator1.next().value); // Array [1, "b"]

iterator.next()返回一个对象,对于有元素的数组,
是next{ value: Array(2), done: false };
next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,直到迭代器结束done才是true。
next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。

var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator1.next().value); // Array [0, "a"]
console.log(iterator1.next().value); // Array [1, "b"]
console.log(iterator1.next().value); // Array [2, "c"]
console.log(iterator.next());  // { value: undefined, done: true }
/*{value: Array(2), done: false}
          done:false
          value:(2) [0, "a"]
           __proto__: Object
*/

6.Array.prototype.push、unishift、shift、pop - 堆栈

var arr1 = [1,2,3]
arr1.push(4) // [1,2,3,4] // 末尾插入
var arr2 = [1,2,3]
arr2.unshift(0) // [0,1,2,3] // 头部前插入
var arr3 = [1,2,3]
arr3.shift() // [2,3] // 删除第一个
var arr4 = [1,2,3]
arr4.pop() // [1,2] // 删除最后一个

7.Array.prototype.reverse 与 sort - 排序

reverse

reverse()  方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组

function reverseArr() {
    const array1 = ['one', 'two', 'three'];
    console.log('array1:', array1);
    // expected output: "array1:" Array ["one", "two", "three"]

    const reversed = array1.reverse();
    console.log('reversed:', reversed);
    // expected output: "reversed:" Array ["three", "two", "one"]

    // Careful: reverse is destructive -- it changes the original array.
    console.log('array1:', array1);
    // expected output: "array1:" Array ["three", "two", "one"]
}
reverseArr()

sort

sort()  方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的

由于它取决于具体实现,因此无法保证排序的时间和空间复杂性。

语法
arr.sort([compareFunction])
参数 compareFunction 可选
用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的 Unicode 位点进行排序。
firstEl 第一个用于比较的元素。
secondEl 第二个用于比较的元素。
返回值 排序后的数组。请注意,数组已原地排序,并且不进行复制。
/* 
如果没有指明 compareFunction ,那么元素会按照转换为的字符串的诸个字符的 Unicode 位点进行排序。
例如 "Banana" 会被排列到 "cherry" 之前。
例如 当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在 Unicode 顺序上 "80" 要比 "9" 要靠前。
*/
function sortArr() {
    const months = ['orange', 'banana', 'Apple', 'watermelon'];
    months.sort();
    console.log(months);
    // expected output: Array ["Apple", "banana", "orange", "watermelon"]

    const array1 = [1, 30, 22, 200, 2111, 100000];
    array1.sort();
    console.log(array1);
    // expected output: Array [1, 100000, 200, 2111, 22, 30]
}
// sortArr()

/* 
如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
*/
function compare(a, b) {
    if (a < b) { // 按某种排序标准进行比较,a 小于 b
        return -1;
    }
    if (a > b) {
        return 1;
    }
    // a must be equal to b
    return 0;
}
var numbers = [4, 2, 5, 1, 3];
// numbers.sort(compare);
// 要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列
numbers.sort((a, b) => a - b);
console.log(numbers);

// 要比较字符串,参考如下
function compareArr() {
    var items = [
        { name: 'Edward', value: 21 },
        { name: 'Sharpe', value: 37 },
        { name: 'And', value: 45 },
        { name: 'The', value: -12 },
        { name: 'Magnetic' },
        { name: 'Zeros', value: 37 }
    ];

    // sort by value
    items.sort(function (a, b) {
        return (a.value - b.value)
    });
    console.log('items: ', items); 
    // items:  [
    //     { name: 'The', value: -12 },
    //     { name: 'Edward', value: 21 },
    //     { name: 'Sharpe', value: 37 },
    //     { name: 'And', value: 45 },
    //     { name: 'Magnetic' },
    //     { name: 'Zeros', value: 37 }
    // ]

    // sort by name
    items.sort(function (a, b) {
        var nameA = a.name.toUpperCase(); // ignore upper and lowercase
        var nameB = b.name.toUpperCase(); // ignore upper and lowercase
        if (nameA < nameB) {
            return -1;
        }
        if (nameA > nameB) {
            return 1;
        }

        // names must be equal
        return 0;
    });
    console.log('items: ', items); 
    // items:  [
    //     { name: 'And', value: 45 },
    //     { name: 'Edward', value: 21 },
    //     { name: 'Magnetic' },
    //     { name: 'Sharpe', value: 37 },
    //     { name: 'The', value: -12 },
    //     { name: 'Zeros', value: 37 }
    // ]
}
compareArr()

8.Array.prototype.concat、join 与 split - 合并拆分

这个比较简单,直接贴代码

// 合并数组
function concatArr(){
    let arr1 = [1,2,3]
    let arr2 = arr1.concat([3,4])
    let arr3 = [...arr1, ...[3,4]] // ES6扩展运算符
    console.log('arr2: ', arr2); // Array [1, 2, 2, 3, 4]
}
concatArr()

// 拆分为字符创或转为数组,join 与 split 均不会改变原数组
function joinSplitArr(){
    let arr1 = [1,2,3]
    let arr2 = arr1.join('/')
    let arr3 = arr2.split('/')
    console.log('arr1: ', arr1); // Array<number> [1, 2, 3]
    console.log('arr2: ', arr2); // String '1/2/3'
    console.log('arr3: ', arr3); // Array<string> ['1', '2', '3']
}
joinSplitArr()

9.Array.prototype.fill、copyWithin、slice、splice - 填充、数组内部浅拷贝、原数组的部分浅拷贝、替换修改数组部分元素

fill 填充

fill()  方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引

// arr.fill(value[, start[, end]])
// 开始与结束位置索引需要满足 [start, end) 即大于等于start 小于 end
const array1 = [1, 2, 3, 4];

console.log(array1.fill(0, 2, 3));
// expected output: [1, 2, 0, 4]

console.log(array1.fill(5, 1));
// expected output: [1, 5, 5, 5]

console.log(array1.fill(6)); // 不填位置则整个数组填充
// expected output: [6, 6, 6, 6]

copyWithin 数组内部浅拷贝

copyWithin()  方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。但是会改变原数组的元素位置

function copyWithArr() {
    // arr.copyWithin(target[, start[, end]]) // target 表示即将被替换的索引
    // 开始与结束位置索引需要满足 [start, end) 即大于等于start 小于 end
    const array1 = ['a', 'b', 'c', 'd', 'e'];
    
    // copy to index 0 the element at index 3
    console.log(array1.copyWithin(0, 3, 4));
    // expected output: Array ["d", "b", "c", "d", "e"]

    // copy to index 1 all elements from index 3 to the end
    console.log(array1.copyWithin(1, 3));
    // expected output: Array ["d", "d", "e", "d", "e"]

    // copy to index 0 all elements from index 1 to the 5
    console.log(array1.copyWithin(0, 1, 5));
    // expected output: Array ["d", "e", "d", "e", "e"]
}
copyWithArr()

slice 原数组的部分浅拷贝

slice()  方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

function sliceArr() {
    const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

    console.log(animals.slice(2));
    // expected output: Array ["camel", "duck", "elephant"]

    console.log(animals.slice(2, 4));
    // expected output: Array ["camel", "duck"]

    // 此处的 -1 即代表反向的第一个索引,即表示索引,与上一个(2, 4)等价
    console.log(animals.slice(2, -1)); 
    // expected output: Array ["camel", "duck"]

    console.log(animals.slice(-2)); // 从后往前复制2个
    // expected output: Array ["duck", "elephant"]

    console.log(animals.slice()); // 相当于直接复制一个新数组,或者slice(0) 也一致
    // expected output: Array ["ant", "bison", "camel", "duck", "elephant"]
}
sliceArr()

splice 替换修改数组部分元素

splice()  方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组

function spliceArr() {
    const months = ['Jan', 'March', 'April', 'June'];
    months.splice(1, 0, 'Feb');
    // inserts at index 1 索引1之后的 0个元素都被 'Feb’替换,即是直接插入
    console.log(months);
    // expected output: Array ["Jan", "Feb", "March", "April", "June"]

    months.splice(3, 2, 'May');
    // replaces 2 element at index 3 索引3之后的 2个元素都被 'May’替换
    console.log(months); 
    // expected output: Array ["Jan", "Feb", "March", "May"]
}
spliceArr()

10.Array.of、Array.isArray - 其他方法

Array.of()

Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

 Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为 7 的空数组(注意: 这是指一个有 7 个空位 (empty) 的数组,而不是由 7 个undefined组成的数组)。

Array.of(7);       // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

Array.isArray 判断是否数组

Array.isArray()  用于确定传递的值是否是一个 Array

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

最后

以上的方式总结只是自己学习总结,有其他方式欢迎各位大佬评论
渣渣一个,欢迎各路大神多多指正,不求赞,只求监督指正( ̄. ̄)
有关文章经常被面试问到可以帮忙留下言,小弟也能补充完善完善一起交流学习,感谢各位大佬(~ ̄▽ ̄)~