新聞中心
大家好,我是前端西瓜哥,今天說一下 JS 的類數(shù)組對象是什么,以及如何將類數(shù)組對象轉(zhuǎn)為數(shù)組。

成都創(chuàng)新互聯(lián)公司主營淶源網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都App制作,淶源h5微信小程序搭建,淶源網(wǎng)站營銷推廣歡迎淶源等地區(qū)企業(yè)咨詢
類數(shù)組對象是什么?
類數(shù)組對象,就是含有 length 屬性的對象,但這個(gè)對象不是數(shù)組。
通常來說還會有 0 ~ length-1 的屬性,結(jié)構(gòu)表現(xiàn)上非常像一個(gè)數(shù)組。
const arrlike = {1:'a', 4: 'd', length: 9};
Array.isArray(arrlike) // false從底層上來看,這個(gè)對象的原型鏈上沒有 Array.prototype,所以我們不能用 Array.prototype 上的 forEach、map 等數(shù)組特有的方法。
關(guān)于原型鏈,可以看我的這篇文章:《如何用原型鏈的方式實(shí)現(xiàn)一個(gè) JS 繼承?》
如果強(qiáng)行給一個(gè)類數(shù)組對象使用 forEach 方法,會得到一個(gè)類型錯(cuò)誤。
function f(a, b) {
arguments.forEach(item => console.log(item));
}
// Uncaught TypeError: arguments.forEach is not a function除了手動創(chuàng)造的類數(shù)組對象,還有以下常見的類數(shù)組對象:
- 普通數(shù)組中的 argument 對象。需要注意的是,箭頭函數(shù)中不存在這個(gè)對象。
- 一些獲取 Dom 集合的方法,如 document.querySelectorAll()、document.getElementsByClassName、document.getElementsByTagName() 也會返回類數(shù)組對象。
下面看看我們有哪些將類數(shù)組轉(zhuǎn)換為數(shù)組的方法。
Array.prototyle.slice.call()
我們可以用 Array.prototyle.slice 內(nèi)置方法。
Array.prototype.slice.call(obj);
[].slice.call(obj);
[] 空數(shù)組效果同 Array.prototype,因?yàn)榭諗?shù)組本身沒有 slice 方法,會走原型鏈拿到 Array.prototype 的方法??諗?shù)組寫法除了短一點(diǎn)沒有任何優(yōu)點(diǎn)。
然后 call 來自 Function.prototype,可以使用一個(gè)指定的 this 值來調(diào)用一個(gè)函數(shù),這里是 Array.prototype.slice。我們不給 slice 方法傳開始和結(jié)束位置參數(shù),這樣就會默認(rèn)取整個(gè)范圍。
slice 的迭代時(shí)會跳過不存在的索引屬性,所以你會看到 empty 的特殊值,和 undefined 還有點(diǎn)不同,你可以認(rèn)為表示未被初始化。forEach、map 這些內(nèi)置方法是會跳過它們不執(zhí)行傳入的回調(diào)函數(shù)的。
一個(gè)例子:
const arrlike = {1:'a', 4: 'd', length: 9};
const arr = Array.prototype.slice.call(arrlike);
console.log(arr);什么原理?
因?yàn)?slice 用于拷貝返回一個(gè)新的子數(shù)組,且只需要被操作的目標(biāo)有 length 屬性就行了。
下面是 Array.prototype.slice 的核心實(shí)現(xiàn),默認(rèn) start 和 end 都在 length 范圍內(nèi)。
Array.prototype.mySlice = function(start, end) {
if (start == undefined) start = 0;
if (end == undefined) end = this.length;
const cloned = new Array(end - start);
for (let i = 0; i < cloned.length; i++) {
// 為了確保不存在的索引保持為 empty 值
if (i in this) {
cloned[i] = this[start + i];
}
}
return cloned;
}你會發(fā)現(xiàn),類數(shù)組對象替換掉這里的 this 后,能拷貝出一個(gè)真正數(shù)組。
Array.from()
ES6 新出的方法,可以將類數(shù)組對象或者是可迭代對象轉(zhuǎn)換為數(shù)組。
const arrlike = {1:'a', 4: 'd', length: 9};
arr = Array.from(arrlike);
console.log(arr);和Array.prototyle.slice.call() 有點(diǎn)不同,不存在的索引的值被設(shè)置了 undefined。
如果一個(gè)對象,既是類數(shù)組對象,又是可迭代對象,Array.from() 方法會使用該對象的迭代器方法。
一般來說,調(diào)用 JS 的內(nèi)置方法返回類數(shù)組對象同時(shí)是可迭代對象,我們通常喜歡用擴(kuò)展運(yùn)算符(...),更優(yōu)雅。
const elCollection = document.getElementsByTagName('div');
const elArray = [...elCollection];結(jié)尾
一般來說,我們在開發(fā)中遇到的類數(shù)組對象都是 JS 內(nèi)置方法返回的,同時(shí)也是可迭代對象,我們一般都是用 [...arrlik] 擴(kuò)展運(yùn)算符,咻咻咻搞定。
如果類數(shù)組對象不是可迭代對象,可以使用Array.prototyle.slice.call() 和 Array.from()。
前者會對不存在的索引維持為 empty,后者則是 undefined。我們可以認(rèn)為基本差別不大,建議用 Array.from(),語義化更好些。
當(dāng)前名稱:JS中的類數(shù)組對象如何轉(zhuǎn)換為數(shù)組?
本文網(wǎng)址:http://m.fisionsoft.com.cn/article/cogosid.html


咨詢
建站咨詢
