在之前介紹模擬函數重載效果的時候,我們看到JS中的函數中,其實有一個「隱形」的東西來存儲實參所有的實參,這個東西就是arguments對象。但在實際使用過程中它的使用方式和數組簡直一模一樣,用起來感覺就是數組,沒有任何毛病,但實際上它並不是一個數組。
arguments看起來,用起來都像是數組
1 調用方法類似:都可以通過中括號下標的形式來訪問具體某個參數。
2 有length屬性:直接可以獲取實參的個數。
3 和數組一樣,用中括號將內容包含起來。
究竟是不是數組?
結合我們之前所學關於數組的知識點,剛好把它們串起來,從三個角度來驗證下arguments是不是數組。
1 如果是數組,就可以使用前面介紹過的數組的方法,比如用push函數給arguments插入一個元素。
結果報錯,arguments並不像正常的數組一樣,有push函數
2 正面確認下,用我們之前判斷數組的方法來判斷一下:
結果為false,直接說明arguments不是數組。
3 這一切從控制臺看的更為真切:
通過toString函數執行結果可以看出,arguments其實是「[object Arguments]」,其實將其直接列印出來的__proto__屬性值就可以看出,arguments是Object。但是,這個arguments對象又跟我們看到的普通(正常)對象又有區別,因為一般的對象是大括號,而arguments對象是中括號,這一點又像數組。
綜上,arguments本質上是對象,而且是具有數組特性的對象,包括表現形式都用中括號,這種就是艱巨對象和數組特性的數據類型就叫做類數組。
橫空出世:類數組
為了更深入的理解類數組,我們一步步來構造一個類數組。。
先從一個普通對象car開始,特別之處在於增加了數字作為屬性,以及增加一個length屬性,這樣,我們就基本可以模擬出數組的使用方式了,並且仍然保持了對象的特性,如下圖
但這個時候,雖然有點像了,但還有兩點沒有做到,一就是這個時候仍然不能使用數組的方法,二就是該對象列印出來還是使用大括號,也就是仍然只是一個對象。下面給這個對象添加數組的方法試試,以push和splice連個函數為例。
可以看到,在Object對象原型上增加數組的push和splice方法後,該對象之前的大括號也變成了數組的中括號,下面試試新增加的方法是否有效
可以看到,push方法成功將新的元素添加到對象中,類數組car就創建完成了。
需要特別說明的是:
1 數組的方法需要挨個添加到類數組中,需要哪個就添加哪個,並不是一次吧數組的所有方法一次性搬過來了
2 在對象中添加數組的位置,除了剛剛的在對象原型上添加,還可以在類數組中單獨添加,這樣只對本類數組有效,剛剛的方法會導致之後所有的對象都自帶添加的數組方法。
在類數組對象中添加數組的操作方法,只在本對象有效,不影響其他對象。
過程有點複雜,但是也正是通過這些,讓我們透過表面的數據類型,有機會窺探原型,數組和對象的背後,看到 一些近乎顛覆三觀的知識。類數組是一個難點,但是因為它兼具對象和數組的特性,非方便,所以經常要使用到,所以必須理解準確到位,使用熟練。
如果有哪裡講的不對或者需要補充,歡迎評論交流。最後來個很奇葩的大廠筆試題,以上知識學懂沒學懂,評論區裡見真章。