三.JavaScript数组总结

303 阅读13分钟

前言本文对js数组的相关基础知识做了很详细的总结,从创建数组,数组的检测与访问,到数组的增删改查,再到数组的es5和es6方法汇总,还有数组遍历,去重,排序等各种方法......


数组是指一组有序数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。

1.创建数组

方式一:使用Array构造函数创建数组

 let 变量名称 = new Array();    // 创建一个空数组
 let 变量名称 = new Array(data1, data2, ...);    // 创建一个带数据的数组
 let 变量名称 = new Array(size); //创建一个指定大小数组,length为size 

方式二:通过字面量创建数组

  let 变量名称 = [];  //创建一个空数组
  let 变量名称 = [data1, data2, ...];

方式三:通过Array的静态方式(ES6)创建数组

  • 1.Array.from()方法从一个类似数组可迭代对象创建一个新的,浅拷贝的数组实例。
// 1.字符串会被拆成单字符数据
console.log(Array.from('foo'));// ["f", "o", "o"]

// 2.将集合和映射转化为新数组
let m = new Map().set(1, 2).set(4, 5).set("a", "b");
     console.log(Array.from(m)); // [[1, 2],[4, 5],["a", "b"]]
let s = new Set().add(1).add(3).add(5);
     console.log(Array.from(s));//[1,3,5]
     
//3.对现有数组执行浅复制
let array1 = [1, 3, 5, 7, 9];
let array2 = Array.from(array1);
   console.log(array2);//1, 3, 5, 7, 9]
   console.log(array1 === array2);//false
   
//4.arguments等类数组和自定义的类数组也可被转化为数组

//5.任何可迭代对象,只要是部署了Iterator接口的数据结构,Array.from都能将其转为数组

Array.from()还可接受第二个可选的映射函数参数mapFunction,以及第三个参数是执行回调函数 mapFunction 时 this 对象;

 const array1 = [1, 3, 5, 7, 9];
 const array2 = Array.from(array1, (x) => {
       return x ** 2;
     });
   console.log(array2);//[1, 9, 25, 49, 81]
  • 2.Array.of() 一组参数转化为数组实例
  console.log(Array.of(0, 2, 4, 6, 8));// [0, 2, 4, 6, 8]

2.数组索引和检测数组

要取得数组的值需要使用中括号并提供相应值的数字索引index; 数组中元素的数量保存在length属性中,它不仅是只读的,可以通过length属性在数组末尾删除或添加元素;

2.1 数组索引

JavaScript 数组的索引是从0开始的,第一个元素的索引为0,最后一个元素的索引等于该数组的长度减1。

//通过index遍历数组
  const arr1 = ["red", "blue", "yellow", "purple"];
      for (let i = 0; i < arr1.length; i++) {
        console.log(arr1[i]);
      }
//删除
const arr = ["red", "blue", "yellow", "purple"];
      arr.length = 2;
      console.log(arr);// ["red", "blue"]
 //后面增加
const arr1 = ["red", "blue", "yellow", "purple"];
      arr1[arr1.length] = "green";
      console.log(arr1);// ["red", "blue", "yellow", "purple", "green"]

2.2 检测数组(四种)

//方法一:ES6中通过Array.isArray()识别
Array.isArray([])//true
Array.isArray({})//false

//方法二:通过 `实例 instanceof 类`:
console.log({} instanceof Array)//false
console.log(['111','222'] instanceof Array)//true

//方法三:constructor
console.log([].constructor.name==='Array')//true
console.log({}.constructor.name==='Object')//true

//方法四:通过Object.prototype.toString.call()
Object.prototype.toString.call({})  //"[object object]"
Object.prototype.toString.call([])  //"[object Array]"

3. 数组的增删改查

3.1 数组的增加

3.1.1 通过下标增加
var arr = [];
arr[0] = 'a';
arr[1] = 'b';
arr[2] = 1;
arr[3] = 2;
console.log(arr); // ["a", "b", 1, 2]
console.log(arr.length); // 4
arr.length = 5; // 改变数组的`length`值为`5`
console.log(arr); // ["a", "b", 1, 2,undefined]
3.1.2 push从后面增加
 var arr = ["蔡徐坤"];
      arr.push("a", "b");
      console.log(arr); //  ["蔡徐坤", "a", "b"]
3.1.3 unshift() 增加到数组前面
var arr = ['a','b'];
arr.unshift(1,2);
console.log(arr); // [1, 2, "a", "b"]
3.1.4 使用splice() 方法指定位置增加

splice()原本的意思是在删除元素的同时可以在指定位置插入新元素,传入3个参数:开始位置,要删除元素个数,要插入的任意多个元素;

var arr = ['a','b','c',1,2];
arr.splice(2,0,'d','c','e');//从第二位删除0个,增加dce
console.log(arr); // ["a", "b", "d", "c", "e", "c", 1, 2]
3.1.5 使用 concat()方法在原有的数组上增加:
var arr = ['a','b','c'];
var arr2 = arr.concat('d',1,2,['e',3]);
console.log(arr); // ["a", "b", "c"]
console.log(arr2); // ["a", "b", "c", "d", 1, 2, "e", 3]

3.2 删除数组

3.2.1 使用pop()方法从末尾删除

pop()方法删除数组的最后一项,同时减少数组的length,返回被删除的项。

var arr = ["a", "b", "c", "d", 1, 2];
let de = arr.pop();
    console.log(arr); // ["a", "b", "c", "d", 1]
    console.log(de);//2
3.2.2 使用shift() 方法从前面删除

shift()删除数组的第一项并返回删除项

var arr = ['a','b','c','d',1,2];
arr.shift();
console.log(arr); // ["b", "c", "d", 1, 2]
3.2.3 使用slice()删除多个

slice() 方法可以给一个数组中删除多个数组项,只不过不同的是, slice() 不会影响原数组,只是会在原数组基础上创建一个数组副本,可以接受一个或两个参数:返回元素的开始索引和结束索引。 简单的概括一句话:slice()利用元素索引值截取数组,包头不包尾;

//          0  1  2  3   4    5
 var arr = [1, 2, 3, 4, "a", "b"];
 var arr2 = arr.slice(2, 4);//包头不包尾,把第二个截取了,但是第4个没截取
 console.log(arr); // [1, 2, 3, 4, "a", "b"]
 console.log(arr2); // [3, 4]
3.2.4 使用splice() 方法指定位置删除

splice()原本的意思是在删除元素的同时可以在指定位置插入新元素,传入3个参数:开始位置,要删除元素个数,要插入的任意多个元素;

var arr = [1,2,3,4,'a','b','c'];
var arr2 = arr.splice(2,2);
console.log(arr); // [1, 2, "a", "b", "c"]
console.log(arr2); // [3, 4]

3.3 更改数组

3.3.1 使用splice() 方法改变一个数组
var arr = [1,2,3,4,5,6];
//从索引值为2的位置开始删除三个并添加三个
var arr2 = arr.splice(2,3,'a','b','c');
console.log(arr); // [1, 2, "a", "b", "c", 6]
console.log(arr2); // [3, 4, 5]

3.4 查询数组

除了用原始的索引号查询数组外,js还提供了许多方法查询数组

3.4.1 通过数组索引值获取对应元素
      var arr = ["蔡徐坤1", "蔡徐坤2", "蔡徐坤3"];
      console.log(arr[0]);
      console.log(arr[1]);
      console.log(arr[arr.length - 1]);
3.4.2 indexOf()通过元素查找索引
  • 1.返回数组中第一个满足条件的索引(从0开始), 不满足返回-1;
  • 2.有两个参数,第一个是要查找的元素;第二个是从哪个位置开始查找。
  • 3.第二个参数如果取值为正,表示从索引值为该位置的地方查找;第二个参数如果取值为负,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。但是查找顺序仍然是从前向后查询数组。
var array = [2, 5, 9];
array.indexOf(2);     // 0
array.indexOf(7);     // -1
array.indexOf(9, 2);  // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

3.4.3 .lastIndexOf()
  • 1 .返回数组中最后一个满足条件的索引(从0开始), 不满足返回-1通过元素查找索引;
  • 2 .查找顺序从后往前
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum5 = num.lastIndexOf(40);
var newNum6 = num.lastIndexOf(40, 1);//从索引1的位置开始向前查找
console.log("newNum5 = " + newNum5);//3
console.log("newNum6 = " + newNum6);//-1
3.4.4 include()
  • 是否至少找到一个与指定元素匹配的项,返回 true 或 false
  • 语法:arr.includes(searchElement[, fromIndex])
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum7 = num.includes(40);
var newNum8 = num.includes(40, 5);//从索引5的位置开始向后查找
console.log(newNum7);//true
console.log(newNum8);//false

3.5 find()返回第一个匹配的元素

  • 1.find()方法对数组中的每一项元素执行一次 callback 函数,直至有一个 callback 返回 true。
  • 2.当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回 undefined。
  • 3.callback函数带有3个参数:当前元素的值、当前元素的索引,以及数组本身。
      var inventory = [
        { name: "apples", quantity: 2 },
        { name: "bananas", quantity: 0 },
        { name: "cherries", quantity: 5 },
      ];

      function findCherries(fruit) {
        return fruit.name === "cherries";
      }

      console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum1 = num.find((item, index) => {
    return item > 40;
})
console.log("newNum1 = " + newNum1);//50

3.6 findIndex()

返回数组中第一个满足条件的索引(从0开始), 不满足返回-1;

var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum2 = num.findIndex((item, index) => {
    return item > 40;
})
console.log("newNum2 = " + newNum2);//4

3.7 使用slice() 方法提取数组的数据:

var arr = [1,2,3,4,5,6];
var arr2 = arr.slice(-3);
console.log(arr); // [1, 2, 3, 4, 5, 6]
console.log(arr2); // [4, 5, 6]

4.ES5数组常用的方法

4.1 数组转换方法

Array.toString():将数组变成由逗号分割的字符串 Array.valueOf():返回数组本身

let array=[10,20,30,40,50];
console.log(array.toString());  // 10,20,30,40,50
console.log(array.valueOf());   // [10,20,30,40,50]

4.2 数组栈方法push()和pop()

栈是一种后进先出的结构,最近添加的项先被删除,数据项的插入(推入push)和删除(弹出pop)只在栈顶发生;
push()从后面增加
pop()方法删除数组的最后一项,同时减少数组的length,返回被删除的项。

4.3 数组队列方法(先进先出

Array.shift(): 从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度
Array.unshift():方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)

let array=[10,20,30,40];
let item=array.shift();
console.log(item);  // 10
console.log(array);// 20,30,40
array.unshift(100,200,300);
console.log(array);// 100,200,300,20,30,40

4.4 数组排序方法

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

let array1=[10,20,30,40,50];
array1.reverse();
console.log(array1);// 50,40,30,20,10

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

【原理】sort()可以接受一个比较函数,用来判断哪个值应该排在前面,比较函数接受两个参数,如果第一个参数应该排在第二个参数前面就返回负值,如果第一个参数应该排在第二个参数后面就返回正值;

 const array = [2, 12, 30, 60, 16, 26, 8, 5, 45];
      //升序
      function compare1(a, b) {
        return a - b;
      }
      //降序
      function compare2(a, b) {
        return b - a;
      }
      const newArr1 = array.sort(compare1);
      console.log(newArr1);
      const newArr2 = array.sort(compare2);
      console.log(newArr2);

简写:

      const array = [2, 12, 30, 60, 16, 26, 8, 5, 45];
      // 升序
      const newArr1 = array.sort((a, b) => a - b);
      console.log(newArr1); //升序[2, 5, 8, 12, 16, 26, 30, 45, 60]
      //降序;
      const newArr2 = array.sort((a, b) => b - a);
      console.log(newArr2); //降序[60, 45, 30, 26, 16, 12, 8, 5, 2]
      console.log(array); //原数组改变[60, 45, 30, 26, 16, 12, 8, 5, 2]

4.5 数组操作方法

4.5.1 Array.concat()

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

let array=[10,20,30,40];
let array1=[50,60];
let newArray=array.concat(array1);
console.log(newArray);  // 10,20,30,40,50,60
let array2=array.concat('20',[50,60],80);
console.log(array2);  // 10,20,30,40,20,50,60,80
4.5.2 Array.slice([start,end])
  • slice() 方法可以给一个数组中删除多个数组项,只不过不同的是, slice() 不会影响原数组,只是会在原数组基础上创建一个数组副本,可以接受一个或两个参数:返回元素的开始索引和结束索引。
  • 简单的概括一句话:slice()利用元素索引值截取数组,包头不包尾;
let array=[10,20,30,40,50,60,70];
let array1=array.slice(1);// 没有结束位置,表示从起始位置到数组末尾
console.log(array1);// 20,30,40,50,60,70
let array2=array.slice(2,5); // 起始位置的索引为2,结束位置的索引为5(不包括结束位置)
console.log(array2);// 30,40,50

/*
注意:如果slice()方法中起始位置或结束位置中有负数,则用数组的长度加上该数来确定,
举个例子:在一个包含5项的数组中slice(-2,-1)和slice(3,4)是一样的,如果结束位置小于起始位置则返回空数组。
*/
4.5.3 Array.splice():
  • 删除 =>可以删除任意数量的项,只需指定两个参数,要删除第一项的位置和要删除的项数
  • 插入=>可以向指定位置插入任意数量的项,只需提供3个参数,起始位置,0,要插入的项,如果要插入多个项,可以传入第n项,第n+1项,...
  • 替换=>可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3个参数,起始位置,要删除的项数和要插入的的任意数量的项,插入的项数不必与删除的项数相等
//Array.splice(index,item)实现删除操作
let array=[10,20,30,40,50];
array.splice(2,2); // 从索引2开始删除两项
console.log(array); //  10,20,50

//Array.splice(start,0,addItem)实现新增操作
let array=[10,20,30];
array.splice(1,0,40,50,60);//  从下标1开始删除0项,新增40,50,60这三项
console.log(array); // 10,40,50,60,20,30

//Array.splice(start,deleteItem,addItem)实现修改操作
let array=[10,20,30,40,50,60,70];
array.splice(2,2,90,100,110); // 从下标2开始删除2项,插入90,100,110这三项
console.log(array);//   10,20,90,100,110,50,60,70
//需要注意的一点是:插入项的时候是插入当前删除项的前面
4.5.4 Array.join()
  • join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
var a = ['Wind', 'Rain', 'Fire'];
var myVar1 = a.join();      // myVar1的值变为"Wind,Rain,Fire"
var myVar2 = a.join(', ');  // myVar2的值变为"Wind, Rain, Fire"
var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire"
var myVar4 = a.join('');    // myVar4的值变为"WindRainFire"

4.6迭代方法

  • Array.every(function(item,index,array)):对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
let arrays=[1,2,3,4,5,4,3,2,1];
let everyResult=arrays.every((item,index,array)=>{
    return  item>10;
})
console.log(everyResult);   // false
  • Array.filter(function(item,index,array)):对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
      let arrays = [1, 2, 3, 4, 5, 4, 3, 2, 1];
      let filterResult = arrays.filter((item, index, array) => {
        return item > 2;
      });
      console.log(filterResult); // 3,4,5,4,3
  • Array.some(function(item,index,array)):对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true
      let arrays = [1, 2, 3, 4, 5, 4, 3, 2, 1];
      let someResult = arrays.some((item, index, array) => {
        return item > 4;
      });
      console.log(someResult); // true
  • Array.forEach(function(item,index,array)):forEach() 方法对数组的每个元素执行一次给定的函数,没有返回值。
let arrays = [1, 2, 3, 4, 5, 4, 3, 2, 1];
arrays.forEach((item,index,array)=>{
    console.log(item);  // 1,2,3,4,5,4,3,2,1
})
  • Array.map(function(item,index,array)):对数组中的每一项运行给定函数,返回每次函数调用的结果返回的数组
let mapResult=arrays.map((item,index,array)=>{
    return item*2;
})
console.log(mapResult);// 2,4,6,8,10,8,6,4,2

4.7 归并方法

Array.reduce():迭代数组的所有项,然后构建一个最终返回的值,从数组的第一项开始,遍历到最后


let array=[1,2,3,4,5];
let sum=array.reduce((prev,cur,index,array)=>{
    return prev+cur
});
console.log(sum);//15

Array.reduceRight():迭代数组的所有项,然后构建一个最终返回的值,从数组的最后一项开始,向前遍历到第一项

let sum2=array.reduceRight((prev,cur,index,array)=>{
    return prev+cur
})
console.log(sum2);

5.ES6数组新增的方法

5.1 Array.from()Array.of()

5.2 Array.copyWithin()填充数组和 Array.fill()批量复制

  • fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
1.fill 方法接受三个参数 value, start 以及 end. start 和 end 参数是可选的, 其默认值分别为 0this 对象的 length 属性值。

2.如果 start 是个负数, 则开始索引会被自动计算成为 length+start, 其中 length 是 this 对象的 length 属性值。如果 end 是个负数, 则结束索引会被自动计算成为 length+end。

3.fill 方法故意被设计成通用方法, 该方法不要求 this 是数组对象。

4.fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。

5.当一个对象被传递给 fill方法的时候, 填充数组的是这个对象的引用。


[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]
Array(3).fill(4);                // [4, 4, 4]
[].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}

// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
  • Array.copyWithin(target,start=0,end=this.length)在当前数组内部,将指定位置的成员复制到其它位置(会覆盖原有成员),然后返回当前数组 *参数:
    • target(必须):从该位置开始替换数据,如果为负值,表示倒数
    • start(可选):从该位置读取数据,默认为0,如果为负值,表示从末尾开始计算
    • end(可选): 到该位置前停止读取数据,默认等于数组长度,如果为负值,表示从末尾开始计算
[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]

5.3 Array.find()Array.findIndex()Array.includes()

6 数组应用

6.1手动实现一个复制数组元素的方法。mySlice方法不传任何参数,则得到的数组的元素的是原数组的每一项。

    <script>
      Array.prototype.mySlice = function mySlice() {
        // this->arr
        let args = [];
        for (let i = 0; i < this.length; i++) {
          args.push(this[i]);
        }
        return args;
      };
      let arr = [10, 20, 30];
      console.log(arr.mySlice());//[10, 20, 30]
      console.log(arr === arr.mySlice());//false

6.2 已知数组[3, 5, -2, 7, 4], 获取数组中的最大值并打印

方法一:

    let arr = [3, 5, -2, 7, 4];
    let max = arr[0];
    for(let i = 1; i < arr.length; i++){
        if(arr[i] > max){
            max = arr[i];
        }
    }
    console.log(max);

方法二:

      let arr = [3, 5, -2, 7, 4];
      let max1 = arr.sort((a, b) => b - a); 
      console.log(max1);//[7, 5, 4, 3, -2]
      let max2 = arr.sort((a, b) => b - a)[0];
      console.log(max2); // 7

方法三:

      let arr = [3, 5, -2, 7, 4];
      let max = arr[0];
      arr.forEach((item) => {
        if (item > max) {
          max = item;
        }
      });
      console.log(max);

方法四:

      let arr = [3, 5, -2, 7, 4];
      // let max = Math.max(...arr);
      let max = Math.max.apply(Math, arr); // max中的this还是Math
      console.log(max);

6.3数组去重

6.3.1.最基本的去重方法

思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。

     function unique(arr) {
        var res = [],
          count = 0;
        //前面一个和后面所有元素比较,所以外层从0开始,内层从1开始
        for (let i = 0; i < arr.length; i++) {
          count++;
          for (let j = i + 1; j < arr.length; j++) {
            if (arr[j] === arr[i]) {
              i++;
            }
            count++;
          }
          res.push(arr[i]);
        }

        console.log(res, count);//[1,2,3,4,6,7,8,10] 59
      }
      let arr = [1, 2, 3, 3, 4, 6, 6, 7, 8, 8, 10, 10];
      unique(arr); 

或者

function unique(arr){
  var res = [arr[0]];
  for(var i=1;i<arr.length;i++){
    var repeat = false;
    for(var j=0;j<res.length;j++){
      if(arr[i] == res[j]){
        repeat = true;
        break;
      }
    }
    if(!repeat){
      res.push(arr[i]);
    }
  }
  return res;
}

更简便的写法:

      function unique(arr) {
        let res = [];
        arr.forEach((item) => {
          if (res.indexOf(item) === -1) {
            res.push(item);
          }
        });
        return res;
      }
      let r = unique([1, 2, 3, 3, 4, 6, 6, 7, 8, 8, 10, 10]);
      console.log(r);
6.3.2 先排序在去重

思路:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组

      function unique(arr) {
        var arr2 = arr.sort((a, b) => a - b);

        var res = [arr2[0]];

        for (var i = 1; i < arr2.length; i++) {
          if (arr2[i] !== res[res.length - 1]) {
            res.push(arr2[i]);
          }
        }
        return res;
      }
      let arr = [11, 22, 23, 77, 66, 33, 44, 45, 56, 66, 77];
      let r = unique(arr);
      console.log(r);
6.3.3 利用对象的属性去重(推荐)

思路:每次取出原数组的元素,然后再对象中访问这个属性,如果存在就说明重复

      let arr = [1, 3, 7, 3, 3, 5, 8, 5, 2, 5, 3];
      function unique(arr) {
        //1.弄一个空对象
        let res = {};
        arr.forEach((item, index) => {
          //2.遍历数组,并把数组的元素作为对象的key存到对象里面,因为对象的key值是唯一的,所以可以去重
          res[arr[index]] = "蔡徐坤";
        });
        console.log(res); //{1: "蔡徐坤", 2: "蔡徐坤", 3: "蔡徐坤", 5: "蔡徐坤", 7: "蔡徐坤", 8: "蔡徐坤"}
        res = Object.keys(res); //取得key值
        console.log(res); // ["1", "2", "3", "5", "7", "8"]
        res = res.map((item) => ~~item);
        console.log(res); // [1, 2, 3, 5, 7, 8]
      }
      unique(arr);
6.3.4 利用下标查询
  function unique(arr){
     var newArr = [arr[0]];
     for(var i=1;i<arr.length;i++){
    if(newArr.indexOf(arr[i]) == -1){
             newArr.push(arr[i]);
        }
        }
        return newArr;
   }
6.3.5 使用ES6 中的Set实现去重(ES6中最常用)
function unique (arr) {
    return Array.from(new Set(arr))
    //return [...(new Set(arr)]
    /*
    使用new Set(arr)把数组去重的同时,转化为类数组对象了,然后用array.from()转化为数组
    */
}
6.3.6 使用es6的filter和indexOf
      let arr = [1, 3, 7, 3, 3, 5, 8, 5, 2, 5, 3];
      function unique(arr) {
        let res = arr.filter((item, index) => {
          return arr.indexOf(item) === index;//不相等就过滤
        });
        console.log(res);
      }
      unique(arr);
6.3.7 使用reduce和includes
      let arr = [1, 3, 7, 3, 3, 5, 8, 5, 2, 5, 3];
      function unique(arr) {
        //reduce(有第一个函数参数,第二个初始值)
        let res = arr.reduce((preArr, currentItem) => {
          return preArr.includes(currentItem)
            ? preArr
            : [...preArr, currentItem];
        }, []);
        console.log(res);
      }
      unique(arr);
6.3.8 使用双重for循环和splice实现去重(ES5)
function unique(array){
    for(let i=0;i<array.length;i++){    // 外层循环元素
        for(let j=i+1;j<array.length;j++){  // 内层进行值比较
            if(array[i]==array[j]){
                array.splice(j,1);
                j--;
            }
        }
    }
    return array;
}
//双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值
//缺点:null直接消失,NaN和{}无法实现去重
6.3.9 使用 includes实现去重
function unique(arr) {
    let array =[];
    for(let i = 0; i < arr.length; i++) {
        if( !array.includes( arr[i]) ) {
            array.push(arr[i]);
        }
    }
    return array
}
6.3.10 使用hasOwnProperty实现去重
function unique(arr) {
    let obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
6.3.11 使用递归实现去重
function unique(arr) {
    var array= arr;
    var len = array.length;
    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })
    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
6.3.12 使用Map数据结构实现去重
function arrayNonRepeatfy(arr) {
    let map = new Map();
    let array = new Array();  // 数组用于返回结果
    for (let i = 0; i < arr.length; i++) {
        if(map .has(arr[i])) {  // 如果有该key值
            map .set(arr[i], true); 
        } else { 
            map .set(arr[i], false);   // 如果没有该key值
            array .push(arr[i]);
        }
    } 
    return array ;
}
//创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

6.4 小练习

1.要求用户输入3个0~9的数, 输出0~9中哪些用户没有输入过, 输入的格式x,y,z

      let str = prompt("请输入三个整数, 用逗号隔开");
     // 字符串的split方法可以根据传入的参数切割字符串, 转换成一个数组之后返回给我们
     let arr = str.split(",");
     for (let i = 0; i < 10; i++) {
       if (arr[0] == i || arr[1] == i || arr[2] == i) {
         continue;
       }
       console.log(i);
     }