美文网首页vue2 世界
完全解析Array.apply(null, { length:

完全解析Array.apply(null, { length:

作者: 前端末晨曦吖 | 来源:发表于2022-09-02 09:30 被阅读0次

    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')
        })
      )
    }
    

    其中这个表达式Array.apply(null, { length: 20 })有点让人费解。第一感觉这个表达式就是为了创建一个长度为20的数组,但表达式Array(20)也可以实现这个功能啊,为啥非要写那么复杂呢?于是乎就想,如果是这样子,那么我把这一段代码换成 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);
    

    效果图:

    对比图.png

    那么按照刚刚的理解,把代码换成这个样子应该是没有问题的。然后运行代码,发现浏览器什么都没有出来,连个错都没有报,这样子就很明显地说明了,刚刚那样子地理解应该是不对的, Array.apply(null, { length: 20 })和Array(20) 这两句代码还是有区别的,那么区别是什么?

    基础1: Array构造函数

    直接调用Array函数跟new方式调用是等价的,即:
    
    let a = Array(2); // 等价于let 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
    

    基础2: apply函数

    ES5开始apply函数的第二个参数除了可以是数组外,还可以是类数组对象(即包含length属性,且length属性值是个数字的对象)。对象{length: 2}就是一个类数组对象,因为没有初始化下标0,1的值,所以获取0,1下标的值得到的都是undefined。

    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})的值

    温故了基础后再看表达式Array.apply(null, { length: 2 })他就等价于:

    // 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函数并不会遍历数组中没有初始化或者被delete的元素(有相同限制还有forEach, reduce方法)。OK,疑问到此终于真相大白了:写这么“复杂”就是为了实现:创建一个长度为20,且每个元素都被初始化的数组。这样map方法就可以循环20次了。

     // 被初始化的数组
     let apply = Array.apply(null, { length: 20 }).map(function (item, index) {
       return {             
         index: index,          // 循环20次
       };
     });
     
     // 未被初始化的数组
     let data = Array(20).map(function (item, index) {
       return {
         index: index,      // 不会被执行
       };
     });
    

    如果为了少写几个字的话还可以把该表达式修改成:

    Array.apply(null, Array(20)); // 第二个参数用Array(20)代替{length: 20}
    

    还可以使用ES6 API创建初始化数组:

    // 方法1:
    Array.from({length: 20})
     
    // 方法2
    Array(20).fill(null)
    

    若对您有帮助,请点击跳转到B站一键三连哦!感谢支持!!!

    相关文章

      网友评论

        本文标题:完全解析Array.apply(null, { length:

        本文链接:https://www.haomeiwen.com/subject/jtrunrtx.html