JS 之 数组篇(Array)

一、判断数组方法总结

  1. 通过Object.prototype.toString.call()

    每一个继承 Object 的对象都有 toString 方法,如果 toString() 没有重写的话,会返回 [Object type],其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString() 时,会直接返回都是内容的字符串,所以我们需要使用call或者apply方法来改变toString()的执行上下文。

    // 这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined ;常用于判断浏览器内置对象时。
    
    Object.prototype.toString.call(['Hello','An']); // "[object Array]"
    Object.prototype.toString.call('An') // "[object String]"
    Object.prototype.toString.call(1) // "[object Number]"
    Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
    Object.prototype.toString.call(null) // "[object Null]"
    Object.prototype.toString.call(undefined) // "[object Undefined]"
    Object.prototype.toString.call(function(){}) // "[object Function]"
    Object.prototype.toString.call({name: 'An'}) // "[object Object]"
    复制代码
  2. 通过instanceof

    []  instanceof Array; // true
    复制代码
    • instanceof 原理
      能在实例的 原型对象链 中找到该构造函数的prototype所指向的 原型对象,就返回true。即:

      // __proto__: 代表原型对象链
      instance.[__proto__...] === instance.constructor.prototype
      
      // return true
      复制代码
  3. 通过ES6 Array.isArrray()

    function isArray(obj){
      return Array.isArrray(obj);
    };
    复制代码
    • instanceof 与 isArray

      当检测Array实例时,Array.isArray 优于 instanceof ,因为 Array.isArray 可以检测出 iframes

    • Array.isArray()Object.prototype.toString.call()

      Array.isArray()是ES6新增的方法,当不存在 Array.isArray() ,可以用 Object.prototype.toString.call() 实现。

4、通过原型链来判断

5、通过Array.prototype.isPrototypeOf

二、数组常用方法

join(): 通过指定连接符生成字符串

2.1 栈方法

栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。而栈的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。

  • push() / pop():数组末尾推入和弹出,改变原数组; push 返回修改后的数组长度, pop 返回移除的项。

2.2 队列方法

队列数据结构的访问规则是 FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。

  • shift():移除数组中的第一项并返回该项,改变原数组;
  • unshift():在数组前端添加任意个项并返回新数组长度,改变原数组;

2.3 重排序方法

  • reverse():反转数组的顺序,改变原数组;

  • sort():默认会采用升序排列数组项,但是为了实现排序,sort()会调用每个数组项的toString(),然后比较得到的字符串,改变原数组

    var arr = [0, 1, 5, 10, 15];
    arr.sort();		// arr=>[0, 1, 10, 15, 5]
    
    // sort()方法可接收一个比较函数作为参数;
    function compare(val1,val2){
        return val1-val2;
    }
    arr.sort(compare);
    // arr => [0, 1, 5, 10, 15]
    复制代码

2.4 操作方法

  • concat(): 可以基于当前数组中的所有项创建一个新数组。即这个方法会先创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。连接数组,(不影响原数组),浅拷贝

  • slice(start, end):基于当前数组中的一个或多个项创建一个新数组。(不改变原数组)

    • 一个参数时,返回从该参数指定位置开始到当前数组末尾的所有项;
    • 两个参数时,返回起始和结束位置之间的项——但不包含结束位置的项;
    • 如果参数有负值,则用数组长度加上该数来确定相应的位置;如果结束位置小于起始位置,返回 []
  • splice(start, number, value...):主要用途是向数组的中部插入项,改变原数组

    • 删除:指定 2 个参数,即要删除第一项的位置和要删除的项数;
    • 插入:指定 3 个参数,即起始位置、0(要删除的项数)和要插入的项。可插入多个项;
    • 替换:指定 3 个参数,即起始位置、要删除的项数和要插入的任意数量的项。

2.5 位置方法

  • indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标

2.6 迭代方法

每个方法都接收两个参数,即要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响 this 的值

传入这些方法中的函数会接收 3 个参数:数组项的值、该项在数组中的位置和数组对象本身。

  • every():如果该函数对每一项都返回 true ,则返回 true;
  • some():如果该函数对任一项返回true,则返回true
  • filter():返回该函数会返回 true 的项组成的数组;
  • forEach():这个方法没有返回值;无法break,可以用try/catchthrow new Error来停止
  • map():返回每次函数调用的结果组成的数组;

2.7 归并方法

reduce()reduceRight()这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。都接受两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。

方法中的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象;这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项,所以第一个参数是数组的第一项,第二个参数是数组的第二项。

  • reduce():从数组的第一项开始,逐个遍历到最后;

  • reduceRight(fn(prev, cur), defaultPrev): 两两执行,prev 为上次化简函数的return

    • 当传入 defaultPrev 时,从第一项开始;
    • 当未传入时,则为第二项
    // 使用 reduce() 执行求数组中所有值的和;
    var arr = [1,2,3,4,5];
    var sum = arr.reduce(function(prev,cur,index,array){
    	return prev+cur;
    })
    // 15
    复制代码

三、数组去重

(1)for循环嵌套,然后splice方法去重

​ 思路:双层循环,外层循环元素,内层循环时比较值,值相同时删除这个值;(ES5中实用)

function unique(arr){
    for(var i=0;i<arr.length;i++){
        for(var j=i+1;j<arr.length;j++){
            if(arr[i]==arr[j]){
                arr.splice(j,1);
                j--;
            }
        }
    }
    return arr;
}
var arr=[1,2,3,3,4];
console.log(unique(arr)); //==>1,2,3,4
复制代码

(2)新建数组,利用indexOf去重

​ 思路:新建一个数组,原数组遍历传入新数组,判断值是否存在,值不存在就加入该新数组中;但是,方法“indexOf”是es5的方法,IE8以下不支持。(es5中较简单)

function unique2(arr){ 
    var newArr = []; //一个新的临时数组
    for(var i = 0; i < arr.length; i++){   //遍历当前数组
    //如果当前数组的第i已经保存进了临时数组,那么跳过,否则把当前项push到临时数组里面 
        if (newArr.indexOf(arr[i]) == -1){ 
            newArr.push(arr[i])
        }; 
    } 
    return newArr; 
}
复制代码

(3)ES6中利用Set高级函数去重

function newArr(arr){
    return Array.from(new Set(arr))
    // Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
}
 
var arr = [1,1,2,9,6,9,6,3,1,4,5];
console.log(newArr(arr))
//这种方法还无法去掉“{}”空对象
复制代码

(4)使用数组自带的filter();

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item) === index;
  });
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
复制代码

(5)利用sort()

思路:先将原数组进行排序,然后对排序后的数组的相邻项进行比较;

缺点:排序改变了原数组;

function unique(arr) {
      arr = arr.sort(); //sort()方法改变了原数组;
      var newArr = [arr[0]];
      for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i - 1]) {
          newArr.push(arr[i])
        }
      }
      return newArr;
    }
复制代码

四、数组的扁平化flatern

将一个多层级的数组[[1,2], 3, [4,5, [6,7, [8, 9, [10, 11]]]]] 按顺序展开到一个数组中.数组的扁平化

function flatern(arr){
    const isArray = arr.some(item => return item instanceof Array)
    if(!isArray) {
        return arr
    }
    const res = Array.prototype.concat.apply([], arr)
    return flatern(res)
}

// 方法二:
const flatten = arr => {
    return arr.reduce((pre, next) => {
        return pre.concat(Array.isArray(next) ? flatten(next) : next);
    }, []);
};
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享