JavaScript偽數組

JavaScript之類數組完全攻略

今天幫大家整理偽數組的概念,我們先來從題目開始分析

先來打造一個很酷的對象如下

1
2
3
4
5
6
7
var obj = {
'0': 'a',
'1': 'b',
'2': 'c',
'length': 3,
'push': Array.prototype.push
}

這時候來打印obj看會長怎樣

乍看之下他還只是一個平常的對象,但其實這個對象這時候已經變成一個類數組了! 我們來對他做以下操作可以更明白

可以發現到這時候他多了一個 3: “d” ,對象原本是不能這樣做的,但是在這邊卻可以實現,因此才對他取名叫做類數組。

如何打造一個類數組對象:

要打造出一個類數組有要打造出一個類數組有幾個條件

  1. 他必須要是一個對象
  2. 屬性要為索引(數字)值
  3. 一定要有length存在
  4. 最好可以加push
  5. 附註: 如果想讓它變得更像數組可以加上splice,如下圖

出問題考考大家

1
2
3
4
5
6
7
8
9
10
11
var obj = {
"2": "c",
"3": "d",
"length": 3,
"push": Array.prototype.push
}

obj.push("f")
obj.push("g")

console.log(obj)

答案:

3的 “d” 居然被 “f” 覆蓋掉了,而且多了一個4 : “g” ,我們來講解一下實現原理!!

原理:

  1. 在講這個之前我們要先觀察Array.prototype.push的實現方法
1
2
3
4
5
6
7
8
9
10
// 以下是push的偽代碼
function ArrayPush() {
var n = TO_UNIT32(this.length) // 被push的數組長度(類數組採用的length就是這個)
var m = %_AraumentsLength() // push的總長度
for (let i = 0; i < m; i++) {
this[i + n] = %_Arauments(i) // 複製給原數組
}
this.length = n + m // 修正最終數組長度
return this.length
}

從第18行可以得知為甚麼Obj一定要有length,再來第20到22行就能知道他push的觀點全是在length上,也就是說在obj對象最該觀察的不是其他元素而是length!

  1. 原題目:
1
2
3
4
5
6
7
8
9
10
11
var obj = {
"2": "c",
"3": "d",
"length": 3,
"push": Array.prototype.push
}

obj.push("f")
obj.push("g")

console.log(obj)

到這邊就能很明瞭,為甚麼 3會變f ,4會變 g

關鍵代碼

1
2
3
for (let i = 0; i < m; i++) {
this[i + n] = %_Arauments(i) // 複製給原數組
}

大家可以想一下i = 0 的情況下會發生甚麼事,是不是this[0 + n]會被push的第一個元素取代,那這裡他的n代表的不就是Obj的 length,那就表示說Obj [3] 會被 f 取代,並且length變4 ,然後Obj[4]再被 g取代,length變5!!這就是這題的實現原理。

感謝觀看~歡迎分享