一文全面掌握JS數組

前言

前面更新了5篇可視化的相關文章:
從表情包來學canvas 從英雄聯盟來學pixi.js 從表情包來學JS動畫
從夢幻西遊學會廣度優先搜索和A*算法 手把手編寫一個VUE簡易SVG動畫組件面試

實習生跟我說看不懂,但願我能更新一些簡單易懂的, ┭┮﹏┭┮,本期更一波JS數組,從用法到常見考點以及手寫數組部分方法,全面掌握數組。算法

數組

數組是指一組數據的集合,其中的每一個數據被稱做元素,在數組中能夠存聽任意類型的元素。數組是一種將一組數據存儲在單個變量名下的優雅方式。canvas

push

做用:向數組的末尾添加一個或更多元素
參數:(item1, item2, ...)
返回值: push完成後數組的新長度數組

let arr = []
arr.push(1)
arr.push(2,3,4)
console.log(arr) // [1, 2, 3, 4]
複製代碼

pop

做用:刪除數組的最後一個元素
參數: 無
返回值: 被刪除的元素markdown

let arr = [1,2,3,4]
let res = arr.pop()
console.log(res, arr) // 4  [1, 2, 3]
複製代碼

shift

做用:刪除數組的第一個元素
參數: 無
返回值: 被刪除的元素app

let arr = [1,2,3,4]
let res = arr.shift()
console.log(res, arr) // 1 [2,3,4]
複製代碼

unshift

做用:從數組的頭部添加元素
參數: (item1, item2, ...)
返回值: 數組的長度dom

let arr = [1,2,3,4]
let res = arr.unshift()
console.log(res, arr) // 1 [2,3,4]
複製代碼

slice

做用:截取新數組
參數:(start,end)
返回值: 截取部分的新數組函數

let arr = [1,2,3,4]
let res = arr.slice(1)
console.log(res, arr) // [2, 3, 4] [1, 2, 3, 4]
複製代碼

splice

做用:截取新數組
參數:(index,howmany,item)post

index howmany item
必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。 要刪除的項目數量。若是設置爲 0,則不會刪除項目。 可選。向數組添加的新項目。

返回值: 截取部分的新數組動畫

let arr = [1,2,3,4]
arr.splice(2, 1, 'test')
console.log(arr) //  [1, 2, "test", 4]
複製代碼

reverse

做用:顛倒數組中元素的順序
參數: 無
返回值: 顛倒順序的數組, 這裏的方法不直接修改原數組,而不是建立新數組

let arr = [1,2,3,4]
let res = arr.reverse()
console.log(res, arr) // [4, 3, 2, 1]  [4, 3, 2, 1] 
複製代碼

join

做用:按照指定的分隔符,將數組分割成字符串
參數: (separator)
返回值: 數組分割後的字符串

let arr = [1,2,3,4]
let res = arr.join('-')
console.log(res, arr) // 1-2-3-4  [1, 2, 3, 4]
複製代碼

concat

做用:拼接兩個或者多個數組
參數: (arr1, arr2, ...)
返回值: 返回拼接後的數組, 該方法不會影響原數組,而是返回新建立的數組

let arr = [1,2,3,4]
let res1 = arr.indexOf(5)
let res2 = arr.indexOf(1)
console.log(res1, res2)
let arr2 = [5,6,7]
let res = arr.concat(arr2)
console.log(res, arr) // [1, 2, 3, 4, 5, 6, 7]  [1, 2, 3, 4]
複製代碼

indexOf

做用:用於查找數組中是否存在某個值
參數: (value) 查找的值
返回值: 若是存在查找的值,返回對應的下標,不然返回-1

let arr = [1,2,3,4]
let res1 = arr.indexOf(5)
let res2 = arr.indexOf(1)
console.log(res1, res2) // -1 0
// 一般咱們用if來判斷indexOf不喜歡用 === -1的寫法, 在一些老代碼中有奇特的寫法
if (!~arr.indexOf(5)) {
    console.log('這寫法好騷啊')
}
// 這樣寫新手容易看不明白,雖是奇技淫巧,但可讀性不高,建議使用includes方法
複製代碼

includes

做用:用於查找數組中是否存在某個值
參數: (value) 查找的值
返回值: 若是存在查找的值,若是存在返回true不然返回false

let arr = [1,2,3,4]
let res1 = arr.includes(5)
let res2 = arr.includes(1)
console.log(res1, res2) // false true

複製代碼

find

做用:用於查找數組中是否存在某個值
參數: (fn) 匹配函數
返回值: 若是存在查找的值,若是返回第一個符合條件的元素不然返回undefined

let arr = [1,2,3,4]
let res1 = arr.find(item => item > 1)
let res2 = arr.find(item => item > 100)
console.log(res1, res2) // 2 undefined
複製代碼

findIndex

做用:用於查找數組中是否存在某個值
參數: (fn) 匹配函數
返回值: 若是存在查找的值,若是返回第一個符合條件的元素下標不然返回-1

let arr = [1,2,3,4]
let res1 = arr.findIndex(item => item === 1)
let res2 = arr.findIndex(item => item === 100)
console.log(res1, res2) // 0 -1
複製代碼

sort

做用:數組排序
參數: (fn) 排序函數
返回值:排序後的數組

V8 引擎 sort 函數使用插入排序和快速排序來實現排序算法,當數組長度小於10採用的是插入排序,否者使用快速排序

let arr = [1,2,3,4]
arr.sort((a,b) => {
    return b - a
})
console.log(arr) // [4,3,2,1]

複製代碼

fill

做用:給數組填充輸入的值
參數:(value)
返回值: 填充後的數組,仍是指向原數組

let arr = [1,2,3,4]
let res = arr.fill(5)
console.log(arr) // [5,5,5,5]
console.log(res) // [5,5,5,5]
複製代碼

map

做用:返回一個新數組,數組中的元素爲原始數組元素調用函數處理後的值
參數:(fn, index, self)
返回值: 計算後的新數組 不影響原來的數組 map() 不會對空數組進行檢測

let arr = [1,2,3,4]
let res = arr.map(item => {
    return item *item
})
console.log(arr, res) // [1, 2, 3, 4]  [1, 4, 9, 16]
// 建立多個模擬數據 不會對空數組進行檢測 須要先fill在map
let mockArr = new Array(10).fill(0).map((item, index) => {
    return `test-${index}`
})
複製代碼

forEach

做用:遍歷數組
參數: (fn, index, self)
返回值: 返回undefined

let arr = [1,2,3,4]
let res = arr.forEach((item, index, self) => {
    console.log(item)
})
console.log(res) // undefined
複製代碼

some

做用:檢測數組中是否有元素知足條件
參數: (fn) 判斷條件函數
返回值: Boolean 知足條件true不然false

let arr = [1, 2, 3, 4];
let res = arr.some(item => item > 0)
console.log(res) // true
複製代碼

every

做用:檢測數組中是否所有元素知足條件
參數: (fn) 判斷條件函數
返回值: Boolean 知足條件true不然false

let arr = [1, 2, 3, 4];
let res1 = arr.every(item =>  item > 0)
let res2 = arr.every(item =>  item > 2)
console.log(res1, res2) // false
複製代碼

filter

做用:按條件過濾返回新數組
參數: (fn) 判斷條件函數
返回值: 返回符合條件的新數組

let arr = [1, 2, 3, 4];
let res = arr.filter(item => {return item > 2})
console.log(arr, res) // [1, 2, 3, 4]  [3, 4]
複製代碼

reduce

做用:接收一個函數做爲累加器,數組中的每一個值(從左到右)開始縮減,最終計算爲一個值。對空數組是不會執行回調函數的 參數: (fn, initialValue)
fn 爲計算函數
fn的參數:

total currentValue currentIndex arr
初始值, 或者計算結束後的返回值 當前元素 前元素的索引 當前元素所屬的數組對象

initialValue 是初始值 返回值: 返回計算結果

let arr = [1, 2, 3, 4]
let res = arr.reduce(function(prev, cur, index, arr) {
    return prev + cur;
})
console.log(arr, res); // [1, 2, 3, 4] 10
複製代碼

Array.isArray

做用:判斷變量是否爲數組
參數: 判斷的變量
返回值: Boolean 知足條件true不然false

let res1 = Array.isArray([])
let res2 =  Array.isArray({})
console.log(res1, res2) // true false
複製代碼

Array.from

做用:從一個相似數組或可迭代對象建立一個新的,淺拷貝的數組實例
參數: (arrayLike, mapFn, thisArg)

arrayLike mapFn thisArg
想要轉換成數組的僞數組對象或可迭代對象 可選,若是指定了該參數,新數組中的每一個元素會執行該回調函數 可選參數,執行回調函數 mapFn 時 this 對象

返回值: 新數組

let res = Array.from(document.querySelectorAll("div"))
console.log(res) 
複製代碼

Array.of

做用:建立新數組
參數: (item...) 要建立的數據
返回值: 建立的新數組

let arr = Array.of(1, 2, 3,4)
console.log(arr) // [1,2,3,4]
複製代碼

數組與純函數

一個函數的返回結果只依賴於它的參數,而且在執行過程裏面沒有反作用,這個函數叫作純函數。
數組中,會改變原數組的方法: splice、reverse、sort、push、pop、shift、unshift、fill。 在數組中,咱們認爲純函數有2個特色

  1. 不改變原數組
  2. 返回一個數組

符合數組純函數條件的有:map、concat、filter、slice

數組方法ES分類

雖然是沒什麼太大意義的八股文,仍是分類一下吧
ES5:
push、 pop、 shift、 unshift、 splice、 slice、 cancat、 sort、 join、 reverse、
indexOf、forEach、 map、 filter、 every、 some、 reduce、 toString、 Arrary.isArray

ES6:
includes flat find findindex fill Array.from Array.of

類數組

不是數組,擁有length屬性,而且屬性key由非負數的下標構成

let arrayLike = {
    length: 4,
    1: 'a',
    2: 'b',
    3: 'c'
}
複製代碼

常見的類數組

  1. 函數內部的argument
  2. document.querySelectorAll 返回的dom元素列表

類數組中數組方法調用

利用Array.prototype調用數組的方法

Array.prototype.slice.call(arrayLike, 1)
複製代碼

類數組轉換數組

  1. 擴展運算符
let arr = [...arrayLike]
複製代碼
  1. Array.from
Array.from(arrayLike)
複製代碼

如何判斷變量是不是數組

  1. Array.isArray
let a = []
console.log(Array.isArray(a)) //true
複製代碼
  1. instanceof
let a = []
console.log(a instanceof Array) //true
複製代碼
  1. constructor
let a = []
console.log(a.constructor Array) //true
複製代碼
  1. Object.toString
let a=[];
console.log(Object.prototype.toString.call(a)==='[object Array]') //true
複製代碼

如何中斷forEach

其實forEach的設計,就是不可中斷的,可是有面試官會問,常見的答案是如下2種。

  1. 捕獲異常 try-catch
  2. 使用every代替

兩種方法都很差,try-catch寫起來相對來講有破壞代碼的感受, 而使用every則違背了題目的意思,並無從本質上解決forEach,只是換了方法。
若是工做上有須要中斷遍歷的時候,仍是儘可能使用for循環,配合break

let arr = [1,2,3,4,5,6,7]
try{
    arr.forEach(item => {
        if(item ===2) {
            trow new Error('中斷')
        }
        console.log(item)
    })
}catch(e) {
    console.log('捕獲異常',e)
}


複製代碼

手寫數組方法

forEach

Array.prototype.myforEach = function(fn) {
    if(typeof fn !== "function"){
        throw "參數必須爲函數"
    }
    let arr = this;
    for(let i = 0; i <arr.length; i++){
        fn(arr[i], i ,arr)
    }
}
複製代碼

every

Array.prototype.every= function(fn){
    if(typeof fn !== "function"){
        throw "參數必須爲函數"
    }
    let arr = this
    for(let i=0;i < arr.length; i++){
        let flag = fn(arr[i], i, arr);
        if( !flag ){
             return false
        }		
    }
    return true
}
複製代碼

手寫完forEach 和 every 也就能明白爲何forEach不能中斷而every能夠中斷了。

flat

數組扁平化在面試中也是算畢竟高頻的題目

function flat(arr, num = 1) {
  return num > 0
    ? arr.reduce(
        (pre, cur) =>
          pre.concat(Array.isArray(cur) ? flat(cur, num - 1) : cur),
        []
      )
    : arr.slice();
}
複製代碼

最後

數組雖然是基礎,也是新手的面試高頻考點,仍是要牢固掌握,文本介紹了數組的基本使用和一些常見考點,但願文章對你有幫助,我是阿隆,咱們下期見。

相關文章
相關標籤/搜索