js數組,相比大家都很熟悉,因為走到哪都要用,但它有個“雙胞胎弟弟” ,叫類數組(也叫僞數組),可能有的人了解,有的人不了解,今天我們來看一看。
什麼是類數組
顧名思義,這玩意兒肯定是個長得像數組,但又不算數組的東西。那到底是個啥,其實它就是一個對象,一個長的像數組的對象。
和數組的差別
那類數組和數組有啥差別:
1、都有length屬性
2、類數組也可以for循環周遊,有的類數組還可以通過 for of 周遊
3、類數組不具備數組的原型方法,是以類數組不可調用相關數組方法(如,push,slicec,concat等等)
都有哪些類數組
常見的類數組有
- 函數的參數arguments
- 通過getElementsByTagName,getElementsByClassName等方法擷取的dom清單(也叫 HTMLCollection)
- 通過querySelectorAll(),getElementsByName等方法擷取的NodeList節點清單
下面,我們來分别看一下這3類 類數組
arguments
arguments是javascript的一個關鍵字。專指函數的參數集合,它包含了函數的所有參數以及其他屬性。它無需定義,可直接在函數體内使用
function args(a, b, c) {
console.log(arguments)
console.log(typeof arguments)
console.log({}.toString.call(arguments))
}
args('a', 'b', 'c')
我們看看輸出結果
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP35ENJpnT3NmaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1YjN1AzNzgTM2AzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
可以看出,arguments包含所有參數,并且存在length屬性,同時可以看出,他的類型是object,并且轉換為string後 是 object Arguments,代表是Arguments對象。同時,可以看到,他還有一個屬性callee,而這個屬性的值好像就是我們定義的這個函數體,那麼我們輸出看一下
function args(a, b, c) {
console.log(arguments.callee)
}
args('a', 'b', 'c')
可以看到,輸出的确實是我們函數自己。那既然表示的自己,請不要随便去調用這個屬性,因為一旦調用,會不斷的調用自己,進入死循環,直到棧溢出。就像下面這樣
function args (a, b, c) {
console.log(123)
arguments.callee()
}
args('a', 'b', 'c')
dom清單(HTMLCollection)
這一類是指通過getElementsByTagName或者 getElementsByClassName 擷取到的dom清單的集合。
<div>今天天氣不太好</div>
<div>因為下雨了</div>
<script>
var domList = document.getElementsByTagName('div')
console.log(domList)
console.log(typeof domList)
console.log({}.toString.call(domList))
</script>
可以看出,domList也存在length屬性。并且,轉換為string後是 object HTMLCollection。代表是HTMLCollection對象
節點清單(NodeList)
通過document.querySelectorAll()或者getElementsByName所擷取的節點的集合
<div class="abc">今天天氣不太好</div>
<div class="abc">因為下雨了</div>
<script>
var nodeList = document.querySelectorAll('div')
console.log(nodeList)
console.log(typeof nodeList)
console.log({}.toString.call(nodeList))
</script>
可以看出,nodeList同樣存在length屬性,且轉換成string後是 object NodeList,代表是NodeList對象。該對象是一個符合Iterator接口規範的對象,故它可以被for…of周遊(什麼是Iterator我就不在這裡講述了,大家可以自己去看 什麼是Iterator)
特點
類數組都不存在數組的原型方法,但當類數組需要調用數組方法去做任何事情時,可以通過以下方式
- 利用call,apply進行方法借用,借用數組的各自方法
- 将類數組轉換為數組。然後再調用數組方法
call,apply進行方法借用
其實我們上面也已經用過這個方法了,類數組轉為字元串時,我們上面是不是借用了對象的toString()方法啊
下面我們再多列幾個
function args(a, b, c) {
Array.prototype.push.call(arguments, '123')
console.log(arguments)
Array.prototype.splice.call(arguments, 0, 1)
console.log(arguments)
Array.prototype.unshift.apply(arguments, [1,2,3])
console.log(arguments)
}
args('a', 'b', 'c')
類數組轉數組
将類數組轉成數組後,就可以随意調用各自數組方法,那麼類數組如何轉成數組呢!
- 可借用數組的一些方法生成一個新數組
function args(a, b, c) {
let arr = Array.prototype.slice.call(arguments)
console.log(arr)
arr = Array.prototype.concat.apply([], arguments)
console.log(arr)
}
args('a', 'b', 'c')
-
利用ES6新增方法轉換為數組
ES6新增了一個Array.from方法,可将類數組轉為數組。還提供了展開運算符,可以直接在一個數組中展開類數組
function args(a, b, c) {
let arr = Array.from(arguments)
console.log(arr)
arr = [...arguments]
console.log(arr)
}
args('a', 'b', 'c')
好了,類數組就寫到這了,歡迎一起探讨