在閱讀VueJS教程時有這麼段demo code:javascript
render: function (createElement) { return createElement('div', Array.apply(null, { length: 20 }).map(function () { return createElement('p', 'hi') }) ) }
其中這個表達式Array.apply(null, { length: 20 })
有點讓人費解。第一感受這個表達式就是爲了建立一個長度爲20的數組,但表達式Array(20)
也能夠實現這個功能啊,爲啥非要寫那麼複雜呢?看來狀況沒那麼簡單。。。html
先溫故下基礎(爲了方便驗證將表達式改爲Array.apply(null, { length: 2 }),即length的值改爲2):vue
直接調用Array函數跟new方式調用是等價的,即:java
var a = Array(2); // 等價於var a = new Array(2);
表示:建立一個長度爲2的數組,注意該數組的元素並無被初始化,即:數組
console.log(0 in a); // false console.log(1 in a); // false, 由於數組下標0,1還未初始化 console.log(a[0]); // undefined, 由於數組下標0還未初始化,訪問不存在的屬性返回undefined
ES5開始apply
函數的第二個參數除了能夠是數組外,還能夠是類數組對象(即包含length屬性,且length屬性值是個數字的對象)。對象{length: 2}
就是一個類數組對象,由於沒有初始化下標0,1的值,因此獲取0,1下標的值獲得的都是undefined。app
console.log(a[0]); // undefined console.log(a[1]); // undefined // 能夠轉成真正的數組 var a = Array.prototype.slice.call({length: 2}); console.log(Array.isArray(a)) // true
溫故了基礎後再看錶達式Array.apply(null, { length: 2 })
他就等價於:ide
// 1 熟悉一點: {length: 2}做爲Array.apply第二個參數等同於[undefined, undefined]做爲Array.apply第二個參數 Array.apply(null, [undefined, undefined]); // 2 再熟悉一點:apply方法的執行結果 Array(undefined, undefined); // 3 再再熟悉一點:Array方法直接調用和new方式調用等價 new Array(undefined, undefined);
這樣就很容易知道該表達式的值是一個長度爲2,且每一個元素值都被初賦值爲undefined的數組(注意此時不是數組元素沒有初始化,而是初始化成undefined,這就是跟Array(2)的區別)。函數
回到最初的問題:爲啥非要寫那麼複雜呢?回答這個問題前還得溫故下map方法(來自MDN描述):ui
It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
即map函數並不會遍歷數組中沒有初始化或者被delete的元素(有相同限制還有forEach, reduce方法)。OK,疑問到此終於真相大白了:寫這麼「複雜」就是爲了實現:建立一個長度爲20,且每一個元素都被初始化的數組。這樣map方法就能夠循環20次了。prototype
// 被初始化的數組 Array.apply(null, {length: 20}).map(function(val, index){ console.log(index); // 循環20次 }); // 未被初始化的數組 Array(20).map(function(val, index){ console.log(index); // 不會被執行 });
其實這已是實現該功能很簡潔的寫法了,不得不佩服vuejs文檔做者的基礎功力。
若是爲了少寫幾個字的話還能夠把該表達式修改爲:
Array.apply(null, Array(20)); // 第二個參數用Array(20)代替{length: 20}
還能夠使用ES6 API更直觀表達意圖:
// 方法1: Array.from({length: 20}) // 方法2 Array(20).fill(null)
Array(2) 等價於[,,],不等價於[undefined, undefined]