Skip to content
目录

数组方法

1、 join()

join(separator): 将数组的元素组起一个字符串,以 separator 为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。

javascript
let arr = [1, 2, 3];
console.log(arr.join()); // '1,2,3'
console.log(arr.join('-')); // '1-2-3'
console.log(arr); // [1, 2, 3](原数组不变)

例子:

通过 join()方法可以实现重复字符串,只需传入字符串以及重复的次数,就能返回重复后的字符串,函数如下:

javascript
function repeatString(str, n) {
    return new Array(n + 1).join(str);
}
console.log(repeatString('abc', 3)); // abcabcabc
console.log(repeatString('Hi', 5)); // HiHiHiHiHi

2、push()和 pop()

push():可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度

pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项

javascript
let arr = ['a', 'b', 'c', 'd'];
let arr1 = arr.push('e');
let arr2 = arr.pop();
console.log(arr1); //5
console.log(arr2); //'e'

3、shift() 和 unshift()

shift()删除原数组第一项,并返回删除元素的值;如果数组为空则返回 undefined 。

unshift():将参数添加到原数组开头,并返回数组的长度

这组方法和上面的 push()和 pop()方法正好对应,一个是操作数组的开头,一个是操作数组的结尾。

javascript
let arr = ['a', 'b', 'c', 'd'];
let arr2 = arr.unshift('X');
let arr1 = arr.shift();
console.log(arr1); //'X'
console.log(arr2); // 5

4、sort()

sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。

在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串,因此会出现以下的这种情况:

javascript
let arr1 = ['a', 'd', 'c', 'b'];
console.log(arr1.sort()); // ["a", "b", "c", "d"]
let arr2 = [13, 24, 51, 3];
console.log(arr2.sort()); // [13, 24, 3, 51]
console.log(arr2); //[13, 24, 3, 51](原数组被改变)

//那么可以借助比较函数
function compare(a, b) {
    return a - b;
}

console.log(arr2.sort(compare)); //[3, 13, 24, 51]

5、reverse()

reverse():反转数组项的顺序。

javascript
let arr = [13, 24, 51, 3];
console.log(arr.reverse()); //[3, 51, 24, 13]
console.log(arr); //[3, 51, 24, 13](原数组改变)

6、concat()

concat():用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

javascript
let arr1 = ['a', 'b', 'c'];
let arr2 = ['d', 'e', 'f'];

let arr3 = arr1.concat(arr2);
// arr3  [ "a", "b", "c", "d", "e", "f" ]

7、slice()

slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。

一个参数:返回从指定位置到末尾的所有项

javascript
var arr=['a','b','c','d'];
var arr1=arr.slice(2);
console.log(arr);//不改变原数组 ["a", "b", "c", "d"]
console.log(arr1);//["c", "d"]
两个参数:

两个参数,返回起始和结束位置之间的项——但不包括结束位置的项。

javascript
var arr = ['a', 'b', 'c', 'd'];
var arr1 = arr.slice(1, 3);
console.log(arr); //["a", "b", "c", "d"]
console.log(arr1); //["b", "c"]

如果两个参数都是负数,所以都加上数组长度 len 转换成正数,arr3 因此相当于 slice(2,4)。

8、splice()

1、删除

javascript
//arr.splice('要删除第一项的位置','删除几项')
var arr = ['a', 'b', 'c', 'd'];
arr.splice(1, 2);
console.log(arr); //["a", "d"]

2、插入或删除

javascript
//arr.splice('要插入的起始位置,删除或替换的项数','要插入的项')
//插入
var arr = ['a', 'b', 'c', 'd'];
arr.splice(1, 0, '插入的第1项', '插入的第2项');
console.log(arr); //["a", "插入的第1项", "插入的第2项", "b", "c", "d"]
//替换
var arr = ['a', 'b', 'c', 'd'];
arr.splice(1, 2, '替换的第1项', '替换的第2项');
console.log(arr); //["a", "替换的第1项", "替换的第2项", "d"]

9、indexOf()和 lastIndexOf()

indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头开始向后查找。

lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符。

javascript
var arr = [1, 3, 5, 7, 7, 5, 3, 1];
console.log(arr.indexOf(5)); //2
console.log(arr.lastIndexOf(5)); //5
console.log(arr.indexOf(5, 2)); //2
console.log(arr.lastIndexOf(5, 4)); //2
console.log(arr.indexOf('5')); //-1

10、forEach()

forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。

这个方法没有返回值

javascript
array.forEach(callback(currentValue, index, array){
    //do something
}, this)

currentValue:当前值

index:当前值的索引

array:要遍历的数组

11、map()

map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

下面代码利用 map 方法实现数组中每个数求平方。

javascript
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item) {
    return item * item;
});
console.log(arr2); //[1, 4, 9, 16, 25]

12、filter()

filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

javascript
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(x, index) {
    return index % 3 === 0 || x >= 8;
});
console.log(arr2); //[1, 4, 7, 8, 9, 10]

13、every()

every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回 true。

javascript
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.every(function(x) {
    return x < 10;
});
console.log(arr2); //true
var arr3 = arr.every(function(x) {
    return x < 3;
});
console.log(arr3); // false

14、some()

some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回 true。

javascript
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.some(function(x) {
    return x < 3;
});
console.log(arr2); //true
var arr3 = arr.some(function(x) {
    return x < 1;
});
console.log(arr3); // false

15、reduce()和 reduceRight()

reduce('前一个值','当前值','当前项索引','数组对象')

这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

下面代码用 reduce()实现数组求和,数组一开始加了一个初始值 10。

javascript
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
});
console.log(arr, sum);

/*
打印结果:
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4, 5] 15
*/

这里可以看出,上面的例子 index 是从 1 开始的,第一次的 prev 的值是数组的第一个值。数组长度是 4,但是 reduce 函数循环 3 次。

js
var  arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
}0) //注意这里设置了初始值
console.log(arr, sum);
/*
打印结果:
0 1 0
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10
*/

这个例子 index 是从 0 开始的,第一次的 prev 的值是我们设置的初始值 0,数组长度是 4,reduce 函数循环 4 次。

结论:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始
注意:如果这个数组为空,运用 reduce 是什么情况?

js
var arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
});
//报错,"TypeError: Reduce of empty array with no initial value"

但是要是我们设置了初始值就不会报错,如下:

js
var  arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
}0)
console.log(arr, sum); // [] 0

所以一般来说我们提供初始值通常更安全

reduce 的简单用法
1):当然最简单的就是我们常用的数组求和,求乘积了。

js
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x, y) => x + y);
var mul = arr.reduce((x, y) => x * y);
console.log(sum); //求和,10
console.log(mul); //求乘积,24
js
//数组对象中值的累加
let array = [
    {
        name: 'apple',
        price: 10
    },
    {
        name: 'banana',
        price: 9
    }
];

let sumprice = 0;
for (let index = 0; index < array.length; index++) {
    const element = array[index];
    sumprice += element.price;
}
console.log('for example sumprice', sumprice);

/* 
        reduce 语法实现
        total    必需。初始值, 或者计算结束后的返回值。
        currentValue    必需。当前元素
        currentIndex    可选。当前元素的索引
        arr    可选。当前元素所属的数组对象。
    */
sumprice = array.reduce(function(total, currentValue, currentIndex, arr) {
    return total + currentValue.price;
}, 0);
console.log('for reduce sumprice', sumprice);

2):计算数组中每个元素出现的次数

js
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre, cur) => {
    if (cur in pre) {
        pre[cur]++;
    } else {
        pre[cur] = 1;
    }
    return pre;
}, {});
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

3):数组去重

js
let arr = [1, 2, 3, 4, 4, 1];
let newArr = arr.reduce((pre, cur) => {
    if (!pre.includes(cur)) {
        return pre.concat(cur);
    } else {
        return pre;
    }
}, []);
console.log(newArr); // [1, 2, 3, 4]

4):将二维数组转化为一维

js
let arr = [[0, 1], [2, 3], [4, 5]];
let newArr = arr.reduce((pre, cur) => {
    return pre.concat(cur);
}, []);
console.log(newArr); // [0, 1, 2, 3, 4, 5]

5):将多维数组转化为一维

js
let arr = [[0, 1], [2, 3], [4, [5, 6, 7]]];
const newArr = function(arr) {
    return arr.reduce(
        (pre, cur) => pre.concat(Array.isArray(cur) ? newArr(cur) : cur),
        []
    );
};
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]

6):对象里的属性求和

js
var result = [
    {
        subject: 'math',
        score: 10
    },
    {
        subject: 'chinese',
        score: 20
    },
    {
        subject: 'english',
        score: 30
    }
];

var sum = result.reduce(function(prev, cur) {
    return cur.score + prev;
}, 0);
console.log(sum); //60

reduceRight()方法:
reduceRight() 方法的功能和 reduce()功能是一样的,不同的是 reduceRight() 从数组的末尾向前将数组中的数组项做累加。

reduceRight() 首次调用回调函数 callbackfn 时,preValue 和 curValue 可以是两个值之一。如果调用 reduceRight()时提供了第二个参数,则 preValue 等于该参数,curValue 等于数组中的最后一个值。如果没有提供,则 preValue 等于数组最后一个值,curValue 等于数组中倒数第二个值。

js
arr.reduceRight(function(preValue, curValue, index, array) {
    console.log(preValue, curValue);
    return preValue + curValue;
}); // 10

/* 4 3
   7 2
   9 1
   10 0
*/

arr.reduceRight(function(preValue, curValue, index, array) {
    console.log(preValue, curValue);
    return preValue + curValue;
}, 5); // 15

/* 
5 4
9 3
12 2
14 1
15 0
*/

ES6 对数组的扩展

16、Array.from()

js
Array.from(arrayLike[, mapFunction[, thisArg]])
  • arrayLike:必传参数,想要转换成数组的伪数组对象或可迭代对象。
  • mapFunction:可选参数,mapFunction(item,index){...} 是在集合中的每个项目上调用的函数。返回的值将插入到新集合中。
  • thisArg:可选参数,执行回调函数 mapFunction 时 this 对象。这个参数很少使用。

例如,让我们将类数组的每一项乘以 2:

js
const someNumbers = { '0': 10, '1': 15, length: 2 };

Array.from(someNumbers, value => value * 2); // => [20, 30]

1、将类数组转换成数组

你会碰到的类数组对象有:函数中的 arguments 关键字,或者是一个 DOM 集合

在下面的示例中,让我们对函数的参数求和:

js
function sumArguments() {
    return Array.from(arguments).reduce((sum, num) => sum + num);
}

sumArguments(1, 2, 3); // => 6

Array.from(arguments) 将类数组对象 arguments 转换成一个数组,然后使用数组的 reduce 方法求和。

此外,Array.from() 的第一个参数可以是任意一个可迭代对象,我们继续看一些例子:

js
Array.from('Hey'); // => ['H', 'e', 'y']
Array.from(new Set(['one', 'two'])); // => ['one', 'two']

const map = new Map();
map.set('one', 1);
map.set('two', 2);
Array.from(map); // => [['one', 1], ['two', 2]]

2、克隆一个数组

Array.from() 可以很容易的实现数组的浅拷贝。

js
const numbers = [3, 6, 9];
const numbersCopy = Array.from(numbers);

numbers === numbersCopy; // => false

深拷贝:

js
function recursiveClone(val) {
    return Array.isArray(val) ? Array.from(val, recursiveClone) : val;
}

const numbers = [[0, 1, 2], ['one', 'two', 'three']];
const numbersClone = recursiveClone(numbers);

numbersClone; // => [[0, 1, 2], ['one', 'two', 'three']]
numbers[0] === numbersClone[0]; // => false

3、使用值填充数组

我们来定义一个函数,创建一个填充相同默认值的数组:

js
const length = 3;
const init = 0;
const result = Array.from({ length }, () => init);

result; // => [0, 0, 0]

esult 是一个新的数组,它的长度为 3,数组的每一项都是 0。调用 Array.from() 方法,传入一个类数组对象 { length } 和 返回初始化值的 mapFunction 函数。

但是,有一个替代方法 array.fill() 可以实现同样的功能。

js
const length = 3;
const init = 0;
const result = Array(length).fill(init);

fillArray2(0, 3); // => [0, 0, 0]

4、使用对象填充数组

当初始化数组的每个项都应该是一个新对象时,Array.from() 是一个更好的解决方案:

js
const length = 3;
const resultA = Array.from({ length }, () => ({}));
const resultB = Array(length).fill({});

resultA; // => [{}, {}, {}]
resultB; // => [{}, {}, {}]

resultA[0] === resultA[1]; // => false
resultB[0] === resultB[1]; // => true

由 Array.from 返回的 resultA 使用不同空对象实例进行初始化。之所以发生这种情况是因为每次调用时,mapFunction,即此处的 () => ({}) 都会返回一个新的对象。

然后,fill() 方法创建的 resultB 使用相同的空对象实例进行初始化。不会跳过空项。

5、生成数字范围

js
function range(end) {
    return Array.from({ length: end }, (_, index) => index);
}

range(4); // => [0, 1, 2, 3]

在 range() 函数中,Array.from() 提供了类似数组的 {length:end} ,以及一个简单地返回当前索引的 map 函数 。这样你就可以生成值范围。

6、数组去重

由于 Array.from() 的入参是可迭代对象,因而我们可以利用其与 Set 结合来实现快速从数组中删除重复项。

js
function unique(array) {
    return Array.from(new Set(array));
}

unique([1, 1, 2, 3, 3]); // => [1, 2, 3]

首先,new Set(array) 创建了一个包含数组的集合,Set 集合会删除重复项。

因为 Set 集合是可迭代的,所以可以使用 Array.from() 将其转换为一个新的数组。

这样,我们就实现了数组去重。

17、Array.of()

将一组值转化为数组

javascript
Array.of(); //[]
Array.of(3, 11, 8); //[3,11,8]

可以用来替代 Array()或 new Array()

18、copyWithin()

target(必需):从该位置开始替换数据。

start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。

end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

javascript
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4);
// [4, 2, 3, 4, 5]

初始位置索引 0 开始替换,读取从 3 位索引开始复制,截止到读取到的 4 位置

19、find() 和 findIndex()

查找第一个符合条件的元素与下标

javascript
let arr = [1, 2, 3, 4, 5, 6];
let arr1 = arr.find(function(item) {
    return item > 3;
});
let arr2 = arr.findIndex(function(item) {
    return item > 3;
});
console.log(arr1); //4找到第一个符合条件的就停止查找
console.log(arr2); //3找到第一个符合条件的下标

20、includes()

数组中是否包含某元素

javascript
[1, 2, 3]
    .includes(2) // true
    [(1, 2, 3)].includes(4) // false
    [(1, 2, NaN)].includes(NaN); // true

21、fill()

填充数组

javascript
let arr = [1, 2, 3, 4];
arr.fill(''); //["哦", "哦", "哦", "哦"]

fill 方法可以接受第二个和第三个参数,用于指定填充的起始位置结束位置

javascript
let arr = [1, 2, 3, 4];
arr.fill('', 1, 3); //[1, "哦", "哦", 4]

22、去重

javascript
const arr=['a','b','c','b','c','c','a'];
//new Set()
Array.from(new Set(arr))
//结构解析
[...new Set(arr)]
//filter
arr.filter((item,index,arr)=>arr.indexOf(item)===index);
//新建数组
let newArr=[];
arr.forEach(item=>{
        if(newArr.indexOf(item)===-1){
            return newArr.push(item)
        }
    });
console.log(newArr)
js
//数组对象的去重
const arr = [
    { id: 1, name: 'aaaa' },
    { id: 1, name: 'bbbb' },
    { id: 2, name: 'cccc' },
    { id: 2, name: 'dddd' },
    { id: 3, name: 'eeee' }
];
// 原始方法
function removeRepeatArrObj(arr) {
    // 创建一个临时变量进行记忆
    var hash = {};
    arr = arr.reduce(function(total, item) {
        // 相同则添加一个空的,不同则push进 累加的数组  --指定id属性
        hash[item.id] = hash[item.id] ? '' : true && total.push(item);
        return total;
    }, []);
    return arr;
}

23、大小排序

javascript
[1, 2, 3, 4].sort((a, b) => a - b); // [1, 2,3,4],默认是升序
[1, 2, 3, 4].sort((a, b) => b - a); // [4,3,2,1] 降序

//冒泡排序
Array.prototype.bubleSort = function() {
    let arr = this,
        len = arr.length;
    for (let outer = len; outer >= 2; outer--) {
        for (let inner = 0; inner <= outer - 1; inner++) {
            if (arr[inner] > arr[inner + 1]) {
                //升序
                [arr[inner], arr[inner + 1]] = [arr[inner + 1], arr[inner]];
                // console.log([arr[inner], arr[inner + 1]]);
            }
        }
    }
    return arr;
};

console.log([99, 2, 3, 4].bubleSort()); //[ 2, 3, 4, 99 ]
//选择排序
Array.prototype.selectSort = function() {
    let arr = this,
        len = arr.length;
    for (let i = 0, len = arr.length; i < len; i++) {
        for (let j = i, len = arr.length; j < len; j++) {
            if (arr[i] > arr[j]) {
                [arr[i], arr[j]] = [arr[j], arr[i]];
            }
        }
    }
    return arr;
};

console.log([99, 2, 3, 4].selectSort()); //[ 2, 3, 4, 99 ]

23、扁平化

1.flat()

指定要提取嵌套数组的结构深度,默认值为 1。 使用 Infinity 作为深度,展开任意深度的嵌套数组

js
//默认深度为1,也可以指定深度,无限深度Infinity
const arr1 = [1, 2, [3, 4, [5, 6]]];
arr1.flat();
//[1, 2, 3, 4, [5, 6]]

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(Infinity);
//[1, 2, 3, 4, 5, 6]

//方法会移除数组中的空项
const arr3 = [1, 2, , 4, 5];
arr3.flat();
// [1, 2, 4, 5]

2.reduce

js
const flattenDeep = arr =>
    arr.reduce(
        (prev, cur) =>
            Array.isArray(cur)
                ? prev.concat(flattenDeep(cur))
                : prev.concat(cur),
        []
    );

3.扩展符

js
let arr = [1, 2, [3, 4, [5, 6]]];

while (arr.some(Array.isArray)) {
    arr = [].concat(...arr);
}
console.log(arr);

4.递归

js
let arr = [1, 2, [3, 4, [5, 6]]];

let result = [];
let fn = arr => {
    arr.forEach((item, index) => {
        if (Array.isArray(item)) {
            fn(item);
        } else {
            result.push(item);
        }
    });
};

fn(arr);

console.log(result);

23、最大值

js
//普通数组
let a = Math.max(...[1, 2, 3, 4]); //4
let b = Math.max.apply(this, [1, 2, 3, 4]); //4
let c = [(1, 2, 3, 4)].reduce((prev, cur, curIndex, arr) => {
    return Math.max(prev, cur);
}, 0); //4
console.log(a);
console.log(b);
console.log(c);

//数组对象中id的最大值
const arr = [{ id: 1, name: 'jack' },{ id: 2, name: 'may' },{ id: 3, name: 'shawn' },{ id: 4, name: 'tony' }]
const arr1 = Math.max.apply(Math, arr.map(item => { return item.id }))
const arr2 = arr.sort((a, b) => { return b.id - a.id })[0].id
console.log(arr1) // 4
console.log(arr2) // 4

24、判断是否包含值

js
[1,2,3].includes(4) //false
[1,2,3].indexOf(4) //-1 如果存在换回索引
[1, 2, 3].find((item)=>item===3)) //3 如果数组中无值返回undefined
[1, 2, 3].findIndex((item)=>item===3)) //2 如果数组中无值返回-1
[1,2,3].some(item=>{
  return item===3
}) //true 如果不包含返回false

25、 类数组转化

js
Array.prototype.slice.call(arguments) //arguments是类数组(伪数组)
Array.prototype.slice.apply(arguments)
Array.from(arguments)
[...arguments]

26、对象和数组转化

js
Object.keys({name:'张三',age:14}) //['name','age']
Object.values({name:'张三',age:14}) //['张三',14]
Object.entries({name:'张三',age:14}) //[[name,'张三'],[age,14]]
Object.fromEntries([name,'张三'],[age,14]) //ES10的api,Chrome不支持 , firebox输出{name:'张三',age:14}

27、交集

js
//普通数组
const arr1 = [1, 2, 3, 4, 5, 8, 9], arr2 = [5, 6, 7, 8, 9];
const intersection = arr1.filter(val => arr2.indexOf(val) > -1)
console.log(intersection) //[5, 8, 9]
//数组对象
const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name5', id: 5 }];
const arr2 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];
const result = arr2.filter(v => arr1.some(n => JSON.stringify(n) === JSON.stringify(v)))
console.log(result);
// [{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name5', id: 5 }]

28、并集

js
//普通数组
const arr1 = [1, 2, 3, 4, 5, 8, 9]
const arr2 = [5, 6, 7, 8, 9];
const result = arr1.concat(arr2.filter(v => !arr1.includes(v)))
console.log(result)s//[1, 2, 3, 4,5, 8, 9]
//数组对象
const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }];
const arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];
let arr3 = arr1.concat(arr2);
let result = [];
let obj = [];
result = arr3.reduce(function (prev, cur, index, arr) {
  obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);
  return prev;
}, []);
console.log(result); 
//[{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]

29、差集

js
//数组arr1相对于arr2所没有的
//普通数组
const arr1 = [1, 2, 3, 4, 5, 8, 9]
const arr2 = [5, 6, 7, 8, 9];
const diff = arr1.filter(item => !new Set(arr2).has(item))
console.log(diff) //[ 1, 2, 3, 4 ]
//数组对象
// 对象数组
let arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }];
let arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];
let result = arr1.filter(function (v) {
  return arr2.every(n => JSON.stringify(n) !== JSON.stringify(v))
})
console.log(result); // [ { name: 'name2', id: 2 }, { name: 'name3', id: 3 } ]

30、补集

两个数组各自没有的集合

js
//普通数组
const arr1 = [1, 2, 3, 4, 5, 8, 9]
const arr2 = [5, 6, 7, 8, 9];
const difference = Array.from(new Set(arr1.concat(arr2).filter(v => !new Set(arr1).has(v) || !new Set(arr2).has(v)))) 
console.log(difference) //[ 1, 2, 3, 4, 6, 7 ]

//数组对象
let arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }];
let arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];
let arr3 = arr1.concat(arr2);
let result = arr3.filter(function (v) {
  return arr1.every(n => JSON.stringify(n) !== JSON.stringify(v)) || arr2.every(n => JSON.stringify(n) !== JSON.stringify(v))
})
console.log(result); // [{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]

31、求和

js
//普通数组
[1, 2, 3, 4].reduce(function (prev, cur) {
  return prev + cur;
}, 0) //10 
//数组对象
const sum = [{age:1},{age:2}].reduce(function (prev, cur) {
  return prev + cur.age;
}, 0) //3
console.log(sum)

32、合并

js
//普通数组
const arr1 =[1, 2, 3, 4].concat([5, 6]) //[1,2,3,4,5,6]
const arr2 =[...[1, 2, 3, 4],...[4, 5]] //[1,2,3,4,5,6]
const arrA = [1, 2], arrB = [3, 4]
const arr3 =[].concat.apply(arrA, arrB)//arrA值为[1,2,3,4]
//数组对象
const arr4 = [{ age: 1 }].concat([{ age: 2 }])
const arr5 = [...[{ age: 1 }],...[{ age: 2 }]]
console.log(arr4) //[ { age: 1 }, { age: 2 } ]
console.log(arr5) // [ { age: 1 }, { age: 2 } ]

33、乱序

js
// 取巧的一种算法,但是每个位置乱序的概率不同
function mixArr(arr) {
    return arr.sort(() => {
        return Math.random() - 0.5;
    })
}
console.log(mixArr([1, 2, 3, 'a', 'b', 'c'])); 
js
// 著名的Fisher–Yates shuffle 洗牌算法
function shuffle(arr){
    let m = arr.length;
    while(m > 1){
        let index = parseInt(Math.random() * m--);
        [arr[index],arr[m]] = [arr[m],arr[index]];
    }
    return arr;
}