Array.prototype.fill() con objeto pasa referencia y no nueva instancia

5 minutos de lectura

Arrayprototypefill con objeto pasa referencia y no nueva instancia
koen morren

Estaba jugando un poco y estaba tratando de instanciar una nueva matriz de longitud xdonde todos los elementos de esa matriz se inicializaron a un valor y:

var arr = new Array(x).fill(y);

Esto funciona bien si el valor de y es otra cosa que un objeto. Lo que significa que si y es un objeto, lo siguiente es cierto:

var arr = new Array(2).fill({});
arr[0] === arr[1]; //is true;
arr[0].test="string";
arr[1].test === 'string'; //is also true;

¿Hay alguna forma de indicar que se debe crear un nuevo objeto para cada elemento mientras se usa la función de relleno? ¿O debería simplemente convertirlo en un bucle?

  • Véase también Declarar matriz de objetos

    – Bergi

    19 sep 2021 a las 18:47

  • Relacionado: Array.push() hace que todos los elementos sean iguales al empujar un objeto.

    – Sebastián Simón

    5 de febrero a las 14:59

1646970188 457 Arrayprototypefill con objeto pasa referencia y no nueva instancia
Oriol

primero puedes fill la matriz con cualquier valor (por ejemplo undefined), y luego podrá usar map:

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

  • además Array.from({length:2}, u => ({}))

    – Slai

    1 de febrero de 2018 a las 22:15

  • El rendimiento de esta forma no es el mejor, lamentablemente. Agregué más explicaciones a mi respuesta a continuación.

    – Kostanos

    27 de agosto de 2020 a las 8:08

  • @Slai muy buena respuesta gracias por eso. Me tomó un tiempo darme cuenta pero valió la pena.

    – Cobre

    29 de marzo de 2021 a las 21:56

Arrayprototypefill con objeto pasa referencia y no nueva instancia
Kostanos

La respuesta aceptada es buena y funcionaría en el 90% de los casos.

Pero si está creando una aplicación JS de alto rendimiento y si trabaja con arreglos grandes/enormes, Matriz.mapa(..) crea grande sobrecarga en ambos: uso de memoria y procesador, ya que crea una copia de una matriz.

Recomiendo usar el clásico. por lazo:

    a = new Array(ARRAY_SIZE);
    for (var i = 0; i < ARRAY_SIZE; i++) {
        a[i] = [];
    }
    // or it's one line alternative
    for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);

Probé seis alternativas y obtuve esto:

  • matriz.mapa()como se propone anteriormente (11x veces!!! Más lento):

     a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
    
  • en bucleel mejor (lo más rápido):

     // Standard multi-line way
     a = new Array(ARRAY_SIZE);
     for (var i = 0; i < ARRAY_SIZE; i++) {
         a[i] = [];
     }
    
     // One line syntax
     for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
    
  • para cada (6x tiempo Más lento):

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

[UPDATE 2020-08-27] Una forma más propuesta por Ilias Karim a continuación

  • Array.from (30x veces!!! más lento) – aparentemente peor en términos de rendimiento, a pesar de la mejor sintaxis 🙁

     a = Array.from({ length: ARRAY_SIZE }, () => []);
    
  • [..Array(..)] (5x veces!!! Más lento)

     a = [...Array(ARRAY_SIZE)].map(_=>([]))
    
  • Array.push(..)segundo lugar en términos de rendimiento (2x veces!!! Más lento)

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

PD. solía este violín para pruebas

  • Esta no es una comparación justa ni válida, porque usted preinicializa la matriz y crea una matriz PACKED para el bucle for. Sus puntos de referencia comparan el tiempo de inicialización de objetos repetidos con la iteración de matriz nativa preiniciada. Quite el llenado previo de la matriz, o cambie los tipos de elementos para que no sean homogéneos, y este punto de referencia se desmorona.

    – usuario120242

    21 de junio de 2020 a las 5:02


  • @ user120242 ¿No entiendo tu comentario? El significado de esta pregunta es sobre: ​​¿cómo inicializar la matriz con valores? Acabo de hacer una comparación con la respuesta aceptada y descubrí la forma más rápida de hacerlo. Si tiene una sugerencia mejor para la inicialización de matrices, compártala con nosotros 🙂

    – Kostanos

    27 de agosto de 2020 a las 7:30

Una solución eficaz:
Array.from({ length: 5 }, () => new Object())

  • Se puede escribir más corto: Array.from({length:5}, _=>{})

    – morfles

    21 de abril de 2020 a las 6:24


  • comprobar jsperf. El valor de microbenchmarks que resiste, el relleno y el mapa aún supera a array.from en Chrome a partir de v80. probablemente porque las matrices PACKED iteran más rápido

    – usuario120242

    21 de junio de 2020 a las 4:41


  • Acabo de agregar esta forma de inicialización a mi respuesta anterior, aparentemente, es la peor forma en términos de rendimiento. En mis pruebas, de esta manera mostró 30 veces más lento resultado en comparación con el normal en bucle

    – Kostanos

    27 de agosto de 2020 a las 7:59

  • @morphles debería ser _=>({}) si desea inicializar objetos. De lo contrario, simplemente llenaría la matriz con undefined.

    – VLAZ

    26 de noviembre de 2020 a las 9:21

Lo más corto posible:

let node =  [...Array(2)].map(_=>({}))
console.log(node)

Arrayprototypefill con objeto pasa referencia y no nueva instancia
james

La respuesta de Ilias Karim es excelente. Acabo de hacer lo siguiente:

a = Array.from({length:l}, () => new Array(c).fill(prefix));

para crear una matriz 2D precargada del tamaño especificado, l por c, llena de prefijo. Ahora mi código puede llenar los espacios en la matriz 2D que necesitan valores sin prefijo.

1646970190 54 Arrayprototypefill con objeto pasa referencia y no nueva instancia
arun d

También puede resolver esto con la siguiente solución.

var arr = new Array(2).fill({});
arr = JSON.parse(JSON.stringify(arr));

1646970190 549 Arrayprototypefill con objeto pasa referencia y no nueva instancia
sam henderson

Escribí una publicación de blog sobre esto: http://www.samhenderson.xyz/posts/12

Pero el TLDR es que si desea evitar encadenar funciones múltiples, por ejemplo fill, map. Y quiere evitar escribir un bucle, entonces puede usar:

const array = Array.from({ length: 2 },()=>({}))

Para una matriz de matrices:

const array = Array.from({ length: 2 },()=>([]))

  • Como mencioné en mi respuesta, este método es el peor en términos de rendimiento…

    – Kostanos

    18 de noviembre de 2021 a las 21:47

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad