js中偽數(shù)組轉真數(shù)組

一坑赡、什么是真數(shù)組(數(shù)組)

所謂真數(shù)組烙如,其實可以直接稱為:數(shù)組。
當一個對象具有以下特點時垮衷,可以稱為數(shù)組:

  • 可以按照索引的方式厅翔,存儲多個數(shù)組
  • 具有l(wèi)ength屬性乖坠,表示數(shù)組內(nèi)數(shù)據(jù)的長度(個數(shù))
  • 對象的原型屬性__proto__搀突,指向Array類,且可以使用Array的原型對象prototype身上的屬性和方法熊泵,如:push仰迁,pop等。如圖1:
圖1:真數(shù)組

二顽分、什么是偽數(shù)組

所謂偽數(shù)組徐许,當一個對象具有以下特點:

  • 具有l(wèi)ength(長度)屬性;
  • 可以使用索引對數(shù)據(jù)進行操作卒蘸;
  • 但是不能使用數(shù)組的方法雌隅,如push,pop等缸沃。如圖2:
圖2:偽數(shù)組

注意:
1.偽數(shù)組一般不會直接創(chuàng)建恰起,而是通過一些js操作得到,如:document.getElementsByName()等趾牧;
2.因為偽數(shù)組具有長度和索引检盼,所以可以使用循環(huán)語句遍歷;
3.并不是能使用部分數(shù)組的方法翘单,就是稱為真數(shù)組吨枉;如圖3:

圖3:依然是偽數(shù)組

4.有些情況下,并不是將偽數(shù)組的原型__proto__屬性設置為Array的原型對象prototype哄芜,就可以使用數(shù)組的方法貌亭。如圖4:

圖4:還是偽數(shù)組

三、如何將偽數(shù)組轉成真數(shù)組

如果在一些情況下认臊,js給我們返回的是偽數(shù)組属提,但是我們想使用真數(shù)組的方法對之進行操作,那么此時就需要將偽數(shù)組轉成真數(shù)組之后,才能繼續(xù)使用冤议。

接下來我們根據(jù)偽數(shù)組和真數(shù)組的區(qū)別和特點斟薇,對偽數(shù)組做一下改造,將偽數(shù)組轉成真數(shù)組恕酸,以完成后續(xù)操作堪滨。

方法1:遍歷:創(chuàng)建一個空數(shù)組,循環(huán)遍歷偽數(shù)組蕊温,將遍歷出的數(shù)據(jù)逐一放在空數(shù)組中

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = [];           // 先創(chuàng)建空數(shù)組
for(var i=0;i<ali.length;i++){  // 循環(huán)遍歷偽數(shù)組
    arr[i] = ali[i];    // 取出偽數(shù)組的數(shù)據(jù)袱箱,逐個放在真數(shù)組中
}

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法2:使用slice方法:利用Array原型對象的slice方法,配合apply义矛,將slice中的this指向偽數(shù)組

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = Array.prototype.slice.apply(ali);

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法3:利用ES6提供的Array的from方法

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = Array.from(ali);

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法4:利用ES6提供的展開運算符(...)

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = [...ali];

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法5:利用原型的復制:將偽數(shù)組的proto復制為Array的prototype发笔。但是這種方法有局限性

  • 手動創(chuàng)建具有索引和長度的對象,作為偽數(shù)組
var obj = {
    0:"a",
    1:"b",
    2:"c",
    length:3
}
console.log(obj);       // {0: "a", 1: "b", 2: "c", length: 3}
// obj.push();          // TypeError: obj.push is not a function

obj.__proto__ = Array.prototype;

console.log(obj);       // ["a", "b", "c"]
obj.push("hello");
console.log(obj);       // ["a", "b", "c", "hello"]
  • arguments也適用
function fn(){
    var arg = arguments;
    console.log(arg);       // ["a", "b", ...]
    // arg.push("hello");   // TypeError: arg.push is not a function

    arg.__proto__ = Array.prototype;

    arg.push("hello");
    console.log(arg);       // ["a", "b", "hello", ...]
}
fn("a","b");
  • 選擇器返回的元素集合不適用凉翻,因為就算將元素集合的原型改成了數(shù)組原型(如圖5)了讨,但元素集合本身是只讀的,依然不能修改
var ali = document.getElementsByTagName('li');
console.log(ali);            // [li, li, li, li]
// ali.push("hello");        // TypeError: ali.push is not a function

ali.__proto__ = Array.prototype;

// ali.push("hello");        // Index property setter is not supported
圖5

但是不是意味著制轰,沒有修改到原數(shù)組的方法就可以使用呢(注意圖5前计,沒有l(wèi)ength屬性)

ali.forEach(val => {
    console.log(val);
});

// 會發(fā)現(xiàn)瀏覽器沒執(zhí)行,原因是此時ali缺少length或length為0
console.log(ali.length);    // 0

需要提前獲取ali的length垃杖,在修改原型之后再手動設置

var ali = document.getElementsByTagName('li');
console.log(ali);            // [li, li, li, li]
// ali.push("hello");        // TypeError: ali.push is not a function

var len = ali.length;        // 獲取初始length
ali.__proto__ = Array.prototype;
ali.length = len;            // 設置給修改原型之后的數(shù)組對象

// ali.push("hello");        // Index property setter is not supported
ali.forEach(val => {
    console.log(val);        // 遍歷打印數(shù)組中的值
});
console.log(ali.length);     // 4

小提示:選擇器返回的元素數(shù)組男杈,使用復制原型方法,還需要手動設置length屬性调俘,且不能使用會改變原數(shù)組的方法伶棒。


以上。
關于偽數(shù)組轉真數(shù)組的方法或技巧彩库,后期繼續(xù)補充...
文中如果紕漏肤无,錯誤,不合理侧巨,描述不清晰舅锄,不準確等問題司忱,歡迎大家留言指正...

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皇忿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坦仍,更是在濱河造成了極大的恐慌爹梁,老刑警劉巖右犹,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異姚垃,居然都是意外死亡念链,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門积糯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掂墓,“玉大人,你說我怎么就攤上這事看成【啵” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵川慌,是天一觀的道長吃嘿。 經(jīng)常有香客問我,道長窘游,這世上最難降的妖魔是什么唠椭? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任跳纳,我火速辦了婚禮忍饰,結果婚禮上,老公的妹妹穿的比我還像新娘寺庄。我一直安慰自己艾蓝,他們只是感情好,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布斗塘。 她就那樣靜靜地躺著赢织,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馍盟。 梳的紋絲不亂的頭發(fā)上于置,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音贞岭,去河邊找鬼八毯。 笑死,一個胖子當著我的面吹牛瞄桨,可吹牛的內(nèi)容都是我干的话速。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼芯侥,長吁一口氣:“原來是場噩夢啊……” “哼泊交!你這毒婦竟也來了乳讥?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤廓俭,失蹤者是張志新(化名)和其女友劉穎云石,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體研乒,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡留晚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了告嘲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片错维。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖橄唬,靈堂內(nèi)的尸體忽然破棺而出赋焕,到底是詐尸還是另有隱情,我是刑警寧澤仰楚,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布隆判,位于F島的核電站,受9級特大地震影響僧界,放射性物質發(fā)生泄漏侨嘀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一捂襟、第九天 我趴在偏房一處隱蔽的房頂上張望咬腕。 院中可真熱鬧,春花似錦葬荷、人聲如沸涨共。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽举反。三九已至,卻和暖如春扒吁,著一層夾襖步出監(jiān)牢的瞬間火鼻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工雕崩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魁索,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓晨逝,卻偏偏與公主長得像蛾默,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捉貌,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容