1.什么是偽數(shù)組战转?
偽數(shù)組(ArrayLike)又稱類數(shù)組躬审,雖然從名字上來看枉证,貌似和數(shù)組很像矮男,但實(shí)際上和數(shù)組有很大區(qū)別:
- 偽數(shù)組是一個(gè)對(duì)象,所以
偽數(shù)組 instanceof Array===false 和 偽數(shù)組 instanceof Object===true 這兩個(gè)等式都成立
- 偽數(shù)組必須含有l(wèi)ength屬性室谚,且必須是 number 類型毡鉴,否則就不叫偽數(shù)組,就是一個(gè)普通對(duì)象而已
- 如果length不為0秒赤,那么必須要有數(shù)值型下標(biāo)(即0或者'0'都可以猪瞬,只要可以通過Number()轉(zhuǎn)換為數(shù)值即可)存儲(chǔ)的數(shù)據(jù)
- 偽數(shù)組不能調(diào)用數(shù)組原型上的方法。就是:xx.push()入篮、xx.slice()陈瘦、xx.indexOf() 等等這些方法都不能用
了解了偽數(shù)組的特點(diǎn)后,我們可以根據(jù)其特點(diǎn)舉幾個(gè)例子
2.舉個(gè)栗子
不是偽數(shù)組
var a = {};
var b = { length: 3 };
是偽數(shù)組
var c = { length: 0 };
var d = { 0: '888', length: 1 };
var e = { 1: 'abc', length: 3 }
var f = { '0': 'abc',1:'test', length: 3 }
var g = { 0: 'abc',2:'test', length: 1 }
我們打印下上面7個(gè)變量的結(jié)果如下:
3.偽數(shù)組轉(zhuǎn)數(shù)組
- 方法一:
Array.prototype.slice.call(arrayLike)
或者Array.prototype.slice.apply(arrayLike)
潮售。
我們知道數(shù)組的slice方法可以對(duì)數(shù)組進(jìn)行切割(不傳參痊项,返回原數(shù)組),返回新數(shù)組酥诽。由于類數(shù)組并沒有數(shù)組的這些方法鞍泉,所以通過前面在javascript中的this指向講解過call的原理,我們可以借用方法肮帐。所以上面代碼的call函數(shù)原理是:
arrayLike.fn1=this //this指向slice
arrayLike.fn1() //即arrayLike調(diào)用fn1也就是slice方法咖驮,所以slice方法中的this指向arrayLike。所以偽數(shù)組被切割成數(shù)組返回出來
Array.prototype上的方法原本只能用來操作array對(duì)象。但用call apply 可以把任意對(duì)象當(dāng)做this傳入某個(gè)方法托修,如此一來忘巧,方法中用到的this的地方就不再局限于原來規(guī)定的對(duì)象,而是得到更廣的適用性睦刃。
- 方法二:
Array.prototype.splice.call(arrayLike, 0)
或者Array.prototype.splice.call(arrayLike, 0)
splice也是數(shù)組的方法袋坑,對(duì)數(shù)組進(jìn)行切割(第一個(gè)參數(shù)為切割起始位置,必填)眯勾,我就不介紹了枣宫。和上面原理一樣。
- 方法三:
Array.prototype.concat.apply([], arrayLike)
- 方法四:使用es6自帶的
Array.from(arrayLike)
方法
4.使用上面轉(zhuǎn)換方法測(cè)試
上面我們舉了幾個(gè)偽數(shù)組的例子以及如何將偽數(shù)組轉(zhuǎn)換為數(shù)組吃环,現(xiàn)在我們對(duì)這些例子進(jìn)行測(cè)試:
1.使用 Array.prototype.slice.call(arrayLike)
注:splice我就不舉列子也颤,和slice一樣。
var translate=function(arrayLike){
return Array.prototype.slice.call(arrayLike)
}
console.log(translate(c),translate(c)[0],translate(c).length);
console.log(translate(d),translate(d)[0],translate(d).length);
console.log(translate(e),translate(e)[0],translate(e).length);
console.log(translate(f),translate(f)[2],translate(f).length);
console.log(translate(g),translate(g)[1],translate(g).length);
運(yùn)行結(jié)果如下:
2.使用 Array.prototype.concat.apply([], arrayLike) 方法
var translate=function(arrayLike){
return Array.prototype.concat.apply([], arrayLike)
}
console.log(translate(c),translate(c)[0],translate(c).length);
console.log(translate(d),translate(d)[0],translate(d).length);
console.log(translate(e),translate(e)[0],translate(e).length);
console.log(translate(f),translate(f)[2],translate(f).length);
console.log(translate(g),translate(g)[1],translate(g).length);
運(yùn)行結(jié)果如下:
3.使用 Array.from(arrayLike) 方法
var translate=function(arrayLike){
return Array.from(arrayLike)
}
console.log(translate(c),translate(c)[0],translate(c).length);
console.log(translate(d),translate(d)[0],translate(d).length);
console.log(translate(e),translate(e)[0],translate(e).length);
console.log(translate(f),translate(f)[2],translate(f).length);
console.log(translate(g),translate(g)[1],translate(g).length);
運(yùn)行結(jié)果如下:
5.對(duì)比
上面測(cè)試結(jié)果:
- 從打印表面上看郁轻,
Array.prototype.concat.apply([], arrayLike)
和Array.from(arrayLike)
所有輸出結(jié)果都一樣翅娶,而Array.prototype.slice.call(arrayLike)
結(jié)果有些許差別 - 如果類數(shù)組length值和所含數(shù)據(jù)個(gè)數(shù)相等,三個(gè)方法結(jié)果都一樣
- 如果類數(shù)組length值大于所含數(shù)據(jù)個(gè)數(shù)好唯,
slice
將所缺失的用empty來補(bǔ)充竭沫,contact和from
用undefined來補(bǔ)充。但是打印缺失的都為undefined骑篙,所以三者只是從形式上有區(qū)別蜕提,使用沒什么區(qū)別 - 如果類數(shù)組length值小于所含數(shù)據(jù)個(gè)數(shù),三個(gè)方法都會(huì)將多余的裁減掉靶端。
6.常見的類數(shù)組對(duì)象
1.arguments對(duì)象
arguments對(duì)象是所有(非箭頭)函數(shù)中都可用的局部變量谎势。你可以使用arguments對(duì)象在函數(shù)中引用函數(shù)的參數(shù)。arguments對(duì)象不是一個(gè)Array杨名。它類似于Array脏榆,但除了length屬性和索引元素之外沒有任何Array屬性。例如台谍,它沒有pop方法须喂。但它可以被轉(zhuǎn)換為一個(gè)真正的Array。
function foo(a, b, c) {
console.log(arguments);
}
foo(1, 2, 3);
打印結(jié)果如下:
2.jquery對(duì)象
//html
<p>1</p>
<p>2</p>
<p>3</p>
//js
console.log($('p'))
3.js獲取dom節(jié)點(diǎn)的方法趁蕊,如getElementById等
//html
<p>1</p>
<p>2</p>
<p>3</p>
//js
console.log('通過querySelectorAll:',document.querySelectorAll("p"))
console.log('通過getElementsByTagName:',document.getElementsByTagName("p"))