你真的瞭解JS數組的那些方法嗎?

寄語:
JS數組的方法很是的豐富和瑣碎,學習和使用過程當中老是須要反覆的記憶、查看文檔,但做爲JS基礎這樣真的不該該,咱們應該把它記得倒背如流,深刻理解纔對。
可是要怎樣才能作到呢?這正是我也本文的初衷,根據我的的經驗總結了一下,但願可以幫助和我同樣困惑的人,搞定這個頭疼的問題。node

數組的建立


數組的建立有三種方式:構造函數方式、字面量方式、ES6新增的Array.of()方法建立。數組

  • 構造函數方式:bash

    let arr = new Array(); // 建立一個空數組
    let arr = new Array(10); // 建立長度爲10的數組
    let arr = new Array('a'); // 建立包含一個字符串元素a的數組
    let arr = new Array(10, 'a'); // 建立包含10和字符串a兩個元素的數組 
    複製代碼

    小結:
    1.new 關鍵字是可省略的
    2.當只傳一個number類型參數時,建立的是參數指定長度的數組。即構造函數形式建立數組,不能建立只包含一個number類型元素的數組app

  • 字面量方式:函數

    let arr = [10, 'a'];  // 字面量方式,即直接給數組賦值
    複製代碼
  • Array.of()方法(ES6新增):
    方法的做用是將一組值(即傳進來的參數)轉換爲數組。
    這個方法彌補了構造函數建立數組的不足。能夠實現建立只有一個number類型元素的數組。學習

    let arr = Array.of(3); 
    console.log(arr); // [3]
    // 參數能夠是各類類型
    let arr1 = Array.of(1, 'a', true, null, undefined, {name: "zhangsan"}, [45]);
    console.log(arr1); // [ 1, 'a', true, null, undefined, { name: 'zhangsan' }, [ 45 ] ]
    複製代碼

數組的檢測


兩種較爲準確的檢測方法:ui

  • 利用對象的toString方法:
    Object.prototype.toString.call([]) === "[object Array]"; // true
  • Array.isArray():
    Array.isArray([1, 2, 3]); // true

數組的屬性


  • length屬性:
    做用:
    • 設置或返回數組的長度
    • 可用來增長和刪除數組項
    let arr = [1, 2];  
    arr.length = 1;  
    console.log(arr); // [1]  
    arr.length = 3;    
    console.log(arr); // [1, , ] 
    複製代碼

數組的方法


JavaScript的數組方法包括數組原型的方法、構造函數的方法(ES6新增部分)
針對每個方法咱們主要了解四個方面:做用、參數、返回值、原數組是否改變
(一). 原型上的方法this

  1. push():
    做用:向數組的末尾添加一項或多項
    參數:ele1[, ele2[, ...[, elen]]]
    返回值:添加元素後數組的長度
    原數組是否改變:是編碼

    let arr = [1, 2, 3];
    let temp = arr.push('a', 'b');
    console.log(arr, temp); // [1, 2, 3, 'a', 'b'] 5
    複製代碼
  2. pop():
    做用:刪除數組最後一項
    參數:無
    返回值:刪除的那一項
    原數組是否改變:是spa

    let arr = [1, 2, 3];
    let temp = arr.pop();
    console.log(arr, temp); // [1, 2] 3
    複製代碼
  3. unshift():
    做用:向數組開頭添加一項或多項
    參數:ele1[, ele2[, ...[, elen]]]
    返回值:添加元素後數組的長度
    原數組是否改變:是

    let arr = [1, 2, 3];
    let temp = arr.unshift('a', 'b');
    console.log(arr, temp); // ['a', 'b', 1, 2, 3] 5
    複製代碼
  4. shift():
    做用:刪除數組第一項
    參數:無
    返回值:刪除的那一項
    原數組是否改變:是

    let arr = [1, 2, 3];  
    let temp = arr.shift();
    console.log(arr, temp); // [2, 3] 1
    複製代碼
  5. splice():
    做用:刪除、插入、替換數組項
    參數:startIndex[, deleteCount[, item1[, ...[, itemN]]]]
    返回值:刪除項組成的數組
    原數組是否改變:是

    let arr = [1, 2, 3];
    
    // 插入元素
    let temp = arr.splice(1, 0, 'a', 'b'); // 在索引1的位置插入元素'a''b' 
    console.log(arr, temp); // [1, 'a', 'b', 2, 3] []
    
    // 刪除元素
    let temp1 = arr.splice(1, 2); // 刪除從索引1的位置開始的2項 
    console.log(arr, temp1); // [1, 2, 3] ['a', 'b']
    
    // 替換一個元素
    let temp2 = arr.splice(1, 1, 'a'); // 將索引1的位置的元素替換爲'a'
    console.log(arr, temp2); // [1, 'a', 3 ] [2]
    
    // 替換多個元素
    let temp3 = arr.splice(0, 2, 'b', 'c'); // 將索引0的位置開始的兩項,替換成’b‘和’c‘
    console.log(arr, temp3); // [’b‘, 'c', 3] [1, 'a']
    
    // 只傳第一個參數,則刪除從第一個參數指定的位置到數組結尾的全部項
    let temp4 = arr.splice(0); //從索引0的位置開始,刪除後面的全部項
    console.log(arr, temp4); // [] [’b‘, 'c', 3]
    複製代碼
  6. copyWithin()
    做用:將數組指定位置(start到end)的元素複製到當前數組的其餘位置(target開始),這種複製會替換原位置的元素(ES6新增)
    參數說明:target[,start[,end]]
    參數說明:

    • target: 複製的目標位置(包括),即要被替換的元素開始的位置
    • start: 要copy的元素的開始位置,默認0
    • end: 要copy的元素的結束位置,默認爲數組最後一個元素

    返回值:複製替換以後的數組
    原數組是否改變:是

    let arr = [1, 2, 3, 4, 5];
    // 用索引0~4範圍內的元素,替換索引3~4範圍內的元素,由於要替換的位置只有兩個,因此只將4,5替換爲了1,2
    let temp = arr.copyWithin(3);
    console.log(arr, temp); //  [1, 2, 3, 1, 2] [1, 2, 3, 1, 2]
    
    let arr1 = [1, 2, 3, 4, 5];
    // 用索引2~4範圍內的元素,替換索引3~4範圍內的元素,由於要替換的位置只有兩個,因此只將4,5替換爲了3,4
    let temp1 = arr1.copyWithin(3, 2);
    console.log(arr1, temp1); // [1, 2, 3, 3, 4] [1, 2, 3, 3, 4]
    複製代碼

    小結:
    總結上述的描述,copyWithin的做用就是在數組長度的範圍內,複製start(包括)到end(不包括)範圍內的元素,而後用上述的元替換掉從target(包括)開始到數組結尾的元素,能替換多少就替換多少

  7. reverse():
    做用:翻轉原數組
    參數:無
    返回值:翻轉後的數組
    原數組是否改變:是

    let arr = [1, 2, 3];
    let temp = arr.reverse();
    console.log(arr, temp); // [ 3, 2, 1 ] [ 3, 2, 1 ]
    複製代碼
  8. sort():
    做用:數組排序
    參數:compareFunction
    參數說明:

    • compareFunction返回值大於0時調換當前比對項的順序,不然順序不 變;
    • 參數能夠不傳,不傳默認按照Unicode編碼的順序排列

    返回值:排序後的數組
    原數組是否改變:是

    // 數組從小到大排序
    let arr = [1, 4, 6, 7, 8, 3, 2];
    let temp = arr.sort((a, b) => {
        return a - b;
    })
    console.log(arr, temp); // [ 1, 2, 3, 4, 6, 7, 8 ] [ 1, 2, 3, 4, 6, 7, 8 ]
    
    // 一個實用的數組排序的例子,根據對象元素的排序,排序對象在數組中的位置
    let objArr = [{id: 3, name: "lilei"},{id: 1, name: "hanmeimei"},{id: 2, name: "yimi"}];
    let tempArr = objArr.sort((a, b) => {
        // 按照id從小到大的順序,對數組中的對象進行排序
        // 這個示例說明回調函數的形參a,b實際就是數組中當前進行比對的兩個元素
        return a.id - b.id;
    }); 
    console.log(objArr); //  [{id: 1, name: 'hanmeimei'}, {id: 2, name: 'yimi'}, { id: 3, name: 'lilei' }]
    console.log(tempArr); // [{id: 1, name: 'hanmeimei'}, {id: 2, name: 'yimi'}, { id: 3, name: 'lilei'}]
    複製代碼
  9. concat():
    做用:基於當前的數組拼接數組
    參數:value1[, value2[, ...[, valueN]]
    參數說明:

    • 參數的類型能夠是任意類型。
    • 不是數組類型直接按順序拼接到數組末尾,數組類型的則將數組元素逐一取出拼接到數組末尾
    • 不傳則至關於複製數組

    返回值:拼接後的數組
    原數組是否改變:否

    let arr = [1,2];
    let temp = arr.concat('a', {id:1}, ['lilei', 'hanmeimei']);
    console.log(arr, temp); // [ 1, 2 ] [ 1, 2, 'a', { id: 1 }, 'lilei', 'hanmeimei']
    
    // 用於複製數組
    let arr = [1, 2];
    let temp = arr.concat();
    console.log(arr, temp);  // [ 1, 2 ] [ 1, 2 ]
    複製代碼
  10. slice():
    做用:基於當前數組的一項或多項建立一個新的數組
    參數:startIndex[,endIndex]
    參數說明:返回的元素包含startIndex位置的元素,但不包括endIndex位置的元素
    返回值:返回截取的元素組成的數組
    原數組是否改變:否

    let arr = [0, 1, 2, 3, 4];
    let temp = arr.slice(1,3); // 返回從索引1(包括)位置到索引3(不包括)位置以前的元素
    console.log(arr, temp); // [0, 1, 2, 3, 4] [1, 2]
    
    // 用於複製數組
    let arr = [0, 1, 2, 3, 4];
    let temp = arr.slice(0); // 返回從索引0(包括)位置到數組結尾的全部元素
    console.log(arr, temp); // [0, 1, 2, 3, 4] [0, 1, 2, 3, 4]
    複製代碼
  11. indexOf():
    做用:從數組開頭查找元素在數組中的索引位置(ES5的方法)
    參數:searchElement[, fromIndex]
    返回值:searchElement在數組中的索引,沒找到searchElement則返回-1
    原數組是否改變:否

    let arr = [1, 2, 3, 4, 5, 6, 2];
    // 從數組開頭開始查找
    let temp = arr.indexOf(2);
    console.log(arr, temp); // [ 1, 2, 3, 4, 5, 6, 2 ] 1
    // 從指定的位置開始查找
    let temp1 = arr.indexOf(2,3); // 從索引3(包括)的位置向後查找元素2
    console.log(arr, temp1); // [ 1, 2, 3, 4, 5, 6, 2 ] 6
    複製代碼
  12. lastIndexOf():
    做用:從數組結尾查找元素在數組中的索引位置(ES5的方法)
    參數:searchElement[, fromIndex]
    返回值:searchElement在數組中的索引,沒找到searchElement則返回-1 原數組是否改變:否

    let arr = [1, 2, 3, 4, 5, 6, 2];
    // 從數組末尾開始查找
    let temp = arr.lastIndexOf(2);
    console.log(arr, temp); // [ 1, 2, 3, 4, 5, 6, 2 ] 6
    // 從指定的位置開始查找
    let temp1 = arr.lastIndexOf(2,3); // 從索引3(包括)的位置向前查找元素2
    console.log(arr, temp1); // [ 1, 2, 3, 4, 5, 6, 2 ] 1
    複製代碼
  13. every():
    做用:對數組中的每一項運行給定函數,若是該函數對每一項都返回true,則返回true(ES5方法)
    參數:callback[, thisArg]
    參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
    返回值:true 或 false
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4];
    let temp = arr.every((item, index, array) => {
        return item > 2;
    });
    console.log(arr, temp); // [ 1, 2, 3, 4 ] false
    
    // 方法的第二個參數可選,做用是設定第一個參數中的this指向,若是使用第二個參數,注意callback不能是箭頭函數
    // 後面的迭代方法涉及此參數的,用法相同,不在贅述
    let arr = [1, 2, 3, 4];
    let temp = arr.every(function(item, index, array) {
        return item > this.id;
    }, {id: 2});
    console.log(arr, temp); // [ 1, 2, 3, 4 ] false
    複製代碼
  14. some():
    做用:對數組中的每一項運行給定函數,若是該函數對任意一項返回true,則返回true(ES5方法)
    參數:callback[, thisArg]
    參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
    返回值:true 或 false
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4];
    let temp = arr.some((item, index, array) => {
        return item > 2;
    });
    console.log(arr, temp); // [ 1, 2, 3, 4 ] true
    複製代碼
  15. filter():
    做用:對數組中的每一項運行給定函數,返回該函數返回true的項組成的數組(ES5方法)
    參數:callback[, thisArg]
    參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
    返回值:函數返回true的項組成的數組
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4];
    let temp = arr.filter((item, index, array) => {
        return item > 2;
    });
    console.log(arr, temp); // [ 1, 2, 3, 4 ] [3, 4]
    複製代碼
  16. map():
    做用:對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組(ES5方法)
    參數:callback[, thisArg]
    參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
    返回值:函數每次調用結果組成的數組
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4];
    let temp = arr.map((item, index, array) => {
        return item * item;
    });
    console.log(arr, temp); // [ 1, 2, 3, 4 ] [ 1, 4, 9, 16]
    複製代碼
  17. forEach():
    做用:對數組中的每一項運行給定函數。無返回值(ES5方法)
    參數:callback[, thisArg]
    參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
    返回值:無
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4];
    let temp = arr.forEach((item, index, array) => {
        // 不會有返回值,但可在這裏執行某些操做
        return item * item;
    });
    console.log(arr, temp); // [ 1, 2, 3, 4 ] undefined
    複製代碼

    注意:
    forEach在全部項都遍歷完成以前,沒法像for循環同樣提早終止循環

  18. reduce():
    做用:從數組的第一項開始,逐步遍歷到最後,迭代數組的全部項(ES5方法)
    參數:callback[, initialValue]
    參數說明:

    • callback迭代函數,有四個參數(prev, cur, index, array)
      • prev 前一個值,(initialValue || 數組第一項 || 上一次迭代的結果)
      • cur 當前迭代項
      • index 當前迭代項索引
      • array 迭代的原數組
    • initialValue 迭代的基礎值,不傳基礎值是數組第一項

    返回值:數組迭代後,總體的迭代結果
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    // 數組求和
    let arr = [1, 2, 3];
    let sum = arr.reduce((prev, cur, index, array) => {
        return prev + cur;
    });
    console.log(arr, sum); // [ 1, 2, 3 ] 6
    
    // 傳initialValue 基礎值的示例
    let sum1 = arr.reduce((prev, cur, index, array) => {
        return prev + cur;
    }, 10);
    // 返回的值是:10+1+2+3
    console.log(arr, sum1); // [ 1, 2, 3 ] 16
    複製代碼

    reduce源碼的實現

    Array.prototype.myReduce = function(callback, initialVal){
       let prev = initialVal || this[0]; 
        for(var i = pre ? 0 : 1; i < this.length; i++){
            prev = callback(prev, this[i], i, this);
       }
       return prev
    }
    複製代碼
  19. reduceRight():
    做用:從數組的最後一項開始,逐步遍歷到第一項,迭代數組的全部項(ES5方法)
    參數:callback[, initialValue]
    參數說明:

    • callback迭代函數,有四個參數(prev, cur, index, array)
      • prev 前一個值,(initialValue || 數組第一項 || 上一次迭代的結果)
      • cur 當前迭代項
      • index 當前迭代項索引
      • array 迭代的原數組
    • initialValue 迭代的基礎值,不傳基礎值是數組第一項

    返回值:數組迭代後,總體的迭代結果
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    // 拼接字符串,從後向前迭代數組進行拼接
    let arr = ['h', 'e', 'l', 'l', 'o'];
    let str = arr.reduceRight((prev, cur, index, array) => {
        return prev + cur;
    });
    console.log(arr, str); // [ 'h', 'e', 'l', 'l', 'o' ] 'olleh'
    複製代碼
  20. find():
    做用:查找數組中第一個符合條件的元素,返回該元素 (ES6新增)
    參數:callback[, thisArg]
    參數說明:參數的使用同上述的forEach、every、map、some、filter方法一致
    返回值:查找到則返回該元素,沒找到返回undefined
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4, 5];
    let temp = arr.find((item, index, array) => {
        return item > 2;
    })
    console.log(arr, temp); // [1, 2, 3, 4, 5] 3
    複製代碼
  21. findIndex():
    做用:查找數組中第一個符合條件的元素所在位置的索引,並返回該索引值
    參數:callback[, thisArg]
    參數說明:參數的使用同上述的forEach、every、map、some、filter方法一致
    返回值:查找到則返回該索引值,沒找到返回-1
    原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。

    let arr = [1, 2, 3, 4, 5];
    let temp = arr.findIndex((item, index, array) => {
        return item > 2;
    })
    console.log(arr, temp); // [1, 2, 3, 4, 5] 2
    複製代碼
  22. fill():
    做用:用指定元素,填充數組從start(包括)到end(不包括)之間的元素,若是該區間內已經有元素,直接替換掉(ES6新增)
    參數:value[, start[, end]]
    返回值:填充後的數組
    原數組是否改變:是

    let arr = [1, 2, 3, 4, 5];
    let temp = arr.fill('a', 2, 4);
    console.log(arr, temp); // [1, 2, 'a', 'a', 5] [1, 2, 'a', 'a', 5]
    複製代碼
  23. includes():
    做用:判斷數組中是否包含指定的元素(ES7新增)
    參數:searchElement[, fromIndex]
    返回值:true或false
    原數組是否改變:否

    let arr = [1, 2, 3, 4, 5];
    let temp = arr.includes(5);
    console.log(arr, temp); // [1, 2, 3, 4, 5] true
    
    // 這個方法彌補了indexOf查看元素時的一個不足,即查找NaN的偏差
    let arr1 = [NaN, 'a'];
    let temp1 = arr1.includes(NaN);
    let temp2 = arr1.indexOf(NaN);
    console.log(temp1, temp2); // true -1
    複製代碼
  24. toString()、toLocalString():
    做用:調用數組每一項的toString()方法,返回的是以逗號分隔的字符串
    參數:無
    返回值:轉化後的字符串
    原字數組是否改變:否

    let arr = [1, [1, 2, [4]], {name: "zhangsan"}, 3];
    let temp = arr.toString();
    console.log(arr); [ 1, [ 1, 2, [ 4 ] ], { name: 'zhangsan' }, 3 ] 
    console.log(temp); // '1,1,2,4,[object Object],3'
    複製代碼
  25. join():
    做用:將數組元素轉化爲字符串(調用每一個元素的toString方法),並使用指定的分隔符(默認爲逗號)進行拼接,返回拼接後的字符串
    參數:分隔符,默認爲逗號(,)
    返回值:拼接後的字符串
    原數組是否改變:否

    let arr = [1, [1, 2, [4]], {name: "zhangsan"}, 3];
    let temp = arr.join();
    console.log(arr); [ 1, [ 1, 2, [ 4 ] ], { name: 'zhangsan' }, 3 ] 
    console.log(temp); // '1,1,2,4,[object Object],3'
    
    // 數組求和
    let arr1 = [1, 2, 3];
    console.log(eval(arr1.join('+'))); // 6
    複製代碼

原型方法的總結:
1. 數組的方法無外乎是對數組的增刪改查、轉換、迭代。增、刪、改都會改變原有的數組,查、轉換的方法不涉及callback參數的不會改變原數組,涉及到的則視狀況而定,迭代方法由於均涉及到callback參數,所以也不肯定。
那麼爲何涉及到callback就不肯定了呢???
首先若是直接在callback中操做原數組,那確定原數組會改變。例如:

let arr = [1,2,3,4];    
let temp = arr.forEach((item,index,array) => {  
   // 直接經過索引操做原數組  
   array[index] *= item;
});  
console.log(arr,temp); // [1, 4, 9, 16] undefined  
複製代碼

若是不是直接操做原數組,而是操做callback的item參數的時,若是item是基本數據類型則原數組中對應的該項元素不會改變,若是是引用類型(數組,對象、函數等)則改變,由於操做引用類型的值,實質是操做該值所在存貯地址的內容,而item對應的原數組中的元素和item是同一引用地址,所以會致使原數組中對應元素改變。(小夥伴們對這裏若是仍是不理解,能夠看下數組方法polyfill的實現,這裏再也不贅述)
2. 全部涉及索引的方法,開始位置都是在操做範疇的,結束位置都是不包括在操做範圍內的

(二).構造函數的方法

  • Array.from():
    做用:將類數組轉化爲數組
    參數:arrayLike[, mapFn[, thisArg]]
    參數說明:

    • arrayLike:類數組對象,能夠是咱們常見的nodeList、arguments、字符串、iterable對象等
    • mapFn: 對轉化後的數組進行操做的回調函數
    • thisArg: 指定mapFun中的this

    返回值:轉化後的數組,若是有mapFn,則返回結果是通過mapFn處理的數組
    原類數組是否改變:不使用mapFn,則類數組不改變。使用mapFn則結果同上述迭代方法中使用callback的狀況一致。

    let str = 'hello';
    let temp = Array.from(str);
    console.log(str, temp); // hello [ 'h', 'e', 'l', 'l', 'o' ]
    let temp1 = Array.from(str, (item, index) => {
        return item.toUpperCase();
    });
    console.log(str, temp1); // hello [ 'H', 'E', 'L', 'L', 'O' ]
    複製代碼

    小結:
    Array.from() 等價於 Array.prototype.slice.call(arguments,0)

數組擴展運算符(ES6新增)


數組的擴展運算符能夠將數組轉化爲以逗號分割的參數序列。
幾個簡單使用的應用場景:

  1. 將數組經過擴展運算符轉化爲參數序列直接傳參,無需使用apply轉化了
    let arr = [1, 2, 3];
    
    // apply寫法
    Math.min.apply(null, arr)
    
    // 擴展運算符寫法
    Math.min(...arr)
    複製代碼
  2. 能夠用於複製和拼接數組
    let arr1 = [2, 3, 4];
    let arr2 = ['a', 'b', 'c'];
    
    // 拼接數組arr1和arr2
    console.log([...arr1, ...arr2]); // [2, 3, 4, 'a', 'b', 'c']
    複製代碼
  3. 可用於將字符串分解爲真正的數組,
    […'hello']  // [ 'h', 'e', 'l', 'l', 'o' ]
    複製代碼

寫在最後


長篇大論了這麼久,不是爲了重複書中或者官方的使用說明。而是再分享一些學習的思路,讓初學者可以更快更準的掌握JavaScript數組,讓停留在會用層次的同窗瞭解它更多。 但願我上述的方法說明可以讓你對JavaScript數組一目瞭然,在各個方法所闡述的幾個方面的對比中,將它更輕易的記住。

相關文章
相關標籤/搜索