首頁 > 軟體

JavaScript中的偽陣列用法及說明

2023-02-12 06:00:42

JavaScript中的偽陣列

1.什麼是偽陣列

JavaScript中存在有一種類陣列,或者說偽陣列。經常見到的偽陣列有函數的arguments物件、dom.querySelectorAll等獲取的NodeList類(NodeList本身具有forEach方法)等。

偽陣列並不是陣列,它沒有繼承Array.prototype,但是它“看起來像陣列”,它本身沒有陣列的標準方法,但是它可以複用這些標準方法。

例子

function arrayLike() {
    arguments.forEach(a => console.log(a));//TypeError: arguments.forEach is not a function
}
arrayLike(1, 2, 3);

如上例所示,arguments物件本身並沒有forEach方法,但是它可以複用陣列的這些標準方法。

例子

function arrayLike() {
    // arguments.forEach(a => console.log(a));
    [].forEach.call(arguments, a => console.log(a));// 1 2 3 通過call改變this指向,呼叫陣列的方法
    [...arguments].forEach(a => console.log(a));// 1 2 3  構建一個真實陣列,然後呼叫陣列的方法
}
arrayLike(1, 2, 3);

2.如何建立一個偽陣列物件

一個陣列物件必然具有兩個特點:

  • 具有一個範圍在  0~232-1 的整型length屬性
  • length屬性大於該物件的最大索引,索引是一個  0-232 -2 範圍內的整數

所以很簡單,只要實現這兩個特點,一個物件就是偽陣列物件了。

例子

const arr = { 1: 'AAA', 3: 'CCC', length: 8, }; [].forEach.call(arr, (item, i) => console.log(item, i)); //AAA 1 CCC 3

3.陣列的concat方法

對於陣列和偽陣列,在陣列的標準方法中,只有concat方法是不通用的,對於一個偽陣列,concat方法會將其作為一個整體連線起來。

例子

console.log([].concat.call(arr, [7, 8]));//[ { '1': 'AAA', '3': 'CCC', length: 8 }, 7, 8 ]
console.log([1, 2].concat([7, 8]));//[ 1, 2, 7, 8 ]

上例展示了陣列和偽陣列呼叫concat的不同結果,在遇到這種情況時,我們只有自己對偽陣列進行轉換,比如:

1.通過slice方法,複製偽陣列

console.log([].concat.call([].slice.call(arr), [7, 8]));
//[ <1 empty item>, 'AAA', <1 empty item>, 'CCC', <4 empty items>, 7, 8 ]

2.通過Symbol.isConcatSpreadable改變對偽陣列物件進行concat操作時的預設行為

const arr = {
    1: 'AAA',
    3: 'CCC',
    length: 8,
    [Symbol.isConcatSpreadable]: true,
};
console.log([].concat.call(arr, [7, 8]));
//[ <1 empty item>, 'AAA', <1 empty item>, 'CCC', <4 empty items>, 7, 8 ]

JavaScript偽陣列變真陣列

首先介紹兩種非常簡單直接的方法(偽陣列為可迭代物件):

[...偽陣列] // ES6的語法糖,直接將偽陣列(物件)變為真陣列
Array.from(偽陣列) // Array中的靜態方法,直接將偽陣列(物件)變為真陣列

下面講解偽陣列和真陣列的區別,還有利用陣列的方法將偽陣列變為真陣列:

偽陣列與真陣列的區別

  • 偽陣列是物件
  • 偽陣列原型是Object,而不是Array
  • 所以偽陣列沒有陣列的方法,如push()、shift()、find()等等
  • 偽陣列的屬性名與陣列的下標相似,以0,1,2,… 等的數位表示,也擁有length屬性

陣列的方法物件能用的上嗎?==> 因為陣列的大部分方法是要遍歷陣列,進行處理再建立一個新陣列放回的,而陣列項的呼叫 arr[i] 這種形式物件也能用,所以偽陣列這個物件能適應部分陣列方法

偽陣列是物件,那怎麼利用陣列的方法呢?==> 可以使用 [].陣列方法.call(偽陣列, 引數...) 或 [].陣列方法.apply(偽陣列, 引數) 來呼叫

所以利用偽陣列與陣列的相似點(屬性與下標相似,擁有length屬性,都可以用 [ ] 呼叫),可以很容易的利用陣列的方法將偽陣列變為真陣列。

// 下面我嘗試使用了陣列中所以可能的方法,得出下列能將偽陣列變為陣列的方法
// 函數中的 arguments 是儲存函數參數列和特殊方法的物件,它是一個偽陣列,我們將以它為例進行嘗試
// 在實際應用中,如果偽陣列為可迭代物件,直接運用前兩種最簡單的方法就夠了

function fun1(v1, v2, v3) {
    console.log('-----------------arguments-------------------')
    console.log(arguments) // Arguments { 0: 1, 1: 2, 2: 3, … }
    console.log(Array.isArray(arguments)) // false
    console.log('------------------------------------')
    
    let x = null  // 定義變數x,接收偽陣列轉化後的結果
    
    // 簡單方法(偽陣列為可迭代物件)
    x = [...arguments]
    
    x = Array.from(arguments)
    
    
    // 呼叫陣列方法
    x = [].filter.call(arguments, v => true)
    
    x = [].map.call(arguments, v => v)
    
    x = [].slice.call(arguments)


    // 上面各個方法呼叫後,成功將偽陣列轉為真陣列,其返回的真陣列都是一樣的,如下
    console.log(x) // Array(3) [ 1, 2, 3 ]
    console.log(Array.isArray(x)) // true
} 

fun1(1, 2, 3)

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com