在阅读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]