Array.apply(null, { length: 1000 })
在閱讀VueJS教程時有這么段demo code:
render: function (createElement) {
return createElement('div',
Array.apply(null, { length: 20 }).map(function () {
return createElement('p', 'hi')
})
)
}
其中這個表達(dá)式Array.apply(null, { length: 20 })有點讓人費解恬叹。第一感覺這個表達(dá)式就是為了創(chuàng)建一個長度為20的數(shù)組晚岭,但表達(dá)式Array(20)也可以實現(xiàn)這個功能啊,為啥非要寫那么復(fù)雜呢对雪?于是乎就想怜庸,如果是這樣子当犯,那么我把這一段代碼換成 Array(20) ,變成下面這樣:
render: function (createElement) {
return createElement('div',
Array(20).map(function () {
return createElement('p', 'hi')
})
)
}
對比代碼:
let apply = Array.apply(null, { length: 20 }).map(function (item, index) {
return {
index: index,
};
});
console.log("Array.apply", apply);
let data = Array(20).map(function (item, index) {
return {
index: index,
};
});
console.log("Array()", data);
效果圖:
那么按照剛剛的理解,把代碼換成這個樣子應(yīng)該是沒有問題的割疾。然后運行代碼嚎卫,發(fā)現(xiàn)瀏覽器什么都沒有出來,連個錯都沒有報宏榕,這樣子就很明顯地說明了拓诸,剛剛那樣子地理解應(yīng)該是不對的, Array.apply(null, { length: 20 })和Array(20) 這兩句代碼還是有區(qū)別的麻昼,那么區(qū)別是什么奠支?
基礎(chǔ)1: Array構(gòu)造函數(shù)
直接調(diào)用Array函數(shù)跟new方式調(diào)用是等價的,即:
let a = Array(2); // 等價于let a = new Array(2);
表示:創(chuàng)建一個長度為2的數(shù)組抚芦,注意該數(shù)組的元素并沒有被初始化倍谜,即:
console.log(0 in a); // false
console.log(1 in a); // false, 因為數(shù)組下標(biāo)0迈螟,1還未初始化
console.log(a[0]); // undefined, 因為數(shù)組下標(biāo)0還未初始化,訪問不存在的屬性返回undefined
基礎(chǔ)2: apply函數(shù)
ES5開始apply函數(shù)的第二個參數(shù)除了可以是數(shù)組外,還可以是類數(shù)組對象(即包含length屬性尔崔,且length屬性值是個數(shù)字的對象)答毫。對象{length: 2}就是一個類數(shù)組對象,因為沒有初始化下標(biāo)0季春,1的值洗搂,所以獲取0,1下標(biāo)的值得到的都是undefined鹤盒。
console.log(a[0]); // undefined
console.log(a[1]); // undefined
// 可以轉(zhuǎn)成真正的數(shù)組
var a = Array.prototype.slice.call({length: 2});
console.log(Array.isArray(a)) // true
再看表達(dá)式Array.apply(null, { length: 2})的值
溫故了基礎(chǔ)后再看表達(dá)式Array.apply(null, { length: 2 })他就等價于:
// 1 熟悉一點: {length: 2}作為Array.apply第二個參數(shù)等同于[undefined, undefined]作為Array.apply第二個參數(shù)
Array.apply(null, [undefined, undefined]);
// 2 再熟悉一點:apply方法的執(zhí)行結(jié)果
Array(undefined, undefined);
// 3 再再熟悉一點:Array方法直接調(diào)用和new方式調(diào)用等價
new Array(undefined, undefined);
這樣就很容易知道該表達(dá)式的值是一個長度為2蚕脏,且每個元素值都被初賦值為undefined的數(shù)組(注意此時不是數(shù)組元素沒有初始化,而是初始化成undefined侦锯,這就是跟Array(2)的區(qū)別)驼鞭。
為啥非要寫那么復(fù)雜呢?
即map函數(shù)并不會遍歷數(shù)組中沒有初始化或者被delete的元素(有相同限制還有forEach, reduce方法)尺碰。OK挣棕,疑問到此終于真相大白了:寫這么“復(fù)雜”就是為了實現(xiàn):創(chuàng)建一個長度為20,且每個元素都被初始化的數(shù)組亲桥。這樣map方法就可以循環(huán)20次了洛心。
// 被初始化的數(shù)組
let apply = Array.apply(null, { length: 20 }).map(function (item, index) {
return {
index: index, // 循環(huán)20次
};
});
// 未被初始化的數(shù)組
let data = Array(20).map(function (item, index) {
return {
index: index, // 不會被執(zhí)行
};
});
如果為了少寫幾個字的話還可以把該表達(dá)式修改成:
Array.apply(null, Array(20)); // 第二個參數(shù)用Array(20)代替{length: 20}
還可以使用ES6 API創(chuàng)建初始化數(shù)組:
// 方法1:
Array.from({length: 20})
// 方法2
Array(20).fill(null)