search

Home  >  Q&A  >  body text

"Array.prototype.fill() uses objects to pass references instead of creating new instances"

<p>I was playing around a bit, trying to instantiate a new array of length <code>x</code>, where all elements of the array were initialized to the value <code>y</code>:< /p> <pre class="brush:php;toolbar:false;">var arr = new Array(x).fill(y);</pre> <p>This method works well if the value of <code>y</code> is not an <strong>object</strong>. That is, if <code>y</code> is an object, then the following conditions are true: </p> <pre class="brush:php;toolbar:false;">var arr = new Array(2).fill({}); arr[0] === arr[1]; //The result is true; arr[0].test = 'string'; arr[1].test === 'string'; //The result is also true;</pre> <p>Is there a way to declare that a new object should be created for each element when using the fill function? Or should I convert it to a loop? </p>
P粉682987577P粉682987577468 days ago455

reply all(2)I'll reply

  • P粉878510551

    P粉8785105512023-08-24 00:43:53

    The accepted answer is great and works 90% of the time.

    However, if you are making a high-performance JS application and are using large/huge arrays, Array.map(..) will create a lot of load in terms of memory and processor usage, Because it creates a copy of the array.

    I recommend using the classic for loop:

    a = new Array(ARRAY_SIZE);
        for (var i = 0; i < ARRAY_SIZE; i++) {
            a[i] = [];
        }
        // 或者使用一行代码的替代方案
        for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);

    I tested six alternatives and got the following results:

    • Array.map(), as above (11 times slower than the original! ):

      a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
    • for loop, best choice (fastest):

      // 标准的多行方式
       a = new Array(ARRAY_SIZE);
       for (var i = 0; i < ARRAY_SIZE; i++) {
           a[i] = [];
       }
      
       // 一行语法
       for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
    • forEach (slower 6 times ):

      a = new Array(ARRAY_SIZE).fill();
       a.forEach((val, i) => {
           a[i] = [];
       })

    [Updated on 2020-08-27] Ilias Karim proposed another method

    • Array.from (30 times slower! ) - Definitely worse in terms of performance, despite having the best syntax :(

      a = Array.from({ length: ARRAY_SIZE }, () => []);
    • [..Array(..)] (5 times slower!)

      a = [...Array(ARRAY_SIZE)].map(_=>([]))
    • Array.push(..), ranked second in terms of performance (2x slower! )

      let a = [], total = ARRAY_SIZE;
       while(total--) a.push([]);

    PS: I tested on this fiddle.

    reply
    0
  • P粉461599845

    P粉4615998452023-08-24 00:21:01

    You can first fill the array with any value (e.g. undefined) and then you can use map:

    var arr = new Array(2).fill().map(u => ({}));
    
    var arr = new Array(2).fill().map(Object);
    

    reply
    0
  • Cancelreply