Lo siento, pero no puedo encontrar un mejor título para mi pregunta, pero intentaré describir mejor mi problema. tengo este codigo:
let pdfInvoice_sub_template = [ {text: '{i}', alignment: 'center'}, {text: 'invoices_sub-{i}-name', alignment: 'left'}, {text: 'invoices_sub-{i}-unit', alignment: 'center'}, ]; temp_pdfSubTemplate = []; for (i = 1; i <= 2; i++) { temp_pdfSubTemplate[i] = pdfInvoice_sub_template; jQuery.each(temp_pdfSubTemplate[i], function (key, val) { document.write(val.text = val.text.replace(/{i}/g, i) + '</br>'); }); }
Y con la esperanza de agregar dos elementos al objeto, así:
temp_pdfSubTemplate [[{ text: '1', alignment: 'center' },{ text: 'invoices_sub-1-name', alignment: 'left' },{ text: 'invoices_sub-1-unit', alignment: 'center' }], [{ text: '2', alignment: 'center' },{ text: 'invoices_sub-2-name', alignment: 'left' },{ text: 'invoices_sub-2-unit', alignment: 'center' }]]
Pero después de ejecutar este código, tengo:
1 invoices_sub-1-name invoices_sub-1-unit 1 invoices_sub-1-name invoices_sub-1-unit
En debug devtools, veo después de la primera iteración que pdfInvoice_sub_template tiene un {i} reemplazado por 1, pero reemplazo {i} en temp_pdfSubTemplate . ¿Por qué sucede de esta manera y qué debo hacer?
¡Gracias!
Aquí está el violinista:
https://jsfiddle.net/xf4j1qpu/1/
Gracias a @Lennholm, quien sugirió la respuesta correcta (ver más abajo), el problema se resolvió. La razón principal es que cuando declaro temp_pdfSubTemplate[i] en un bucle, no creo un objeto nuevo, sino que hago referencia al objeto original pdfInvoice_sub_template y, como resultado, las manipulaciones en el bucle se realizan en el objeto original.
El problema tiene dos soluciones.
Además, como sugiere @Lennholm, en lugar de declarar una variable con el objeto original, cree una función cuya única tarea sea crear el objeto que necesito (ver ejemplo en respuesta de @Lennholm). Así, al crear una variable en un bucle, no será solo una referencia al objeto original, sino que se creará uno nuevo.
Como segunda solución es mover las declaraciones del objeto original al comienzo del bucle. Por lo tanto, también se logra el resultado deseado. En cada nuevo bucle, se creará un nuevo objeto:
temp_pdfSubTemplate = []; for (i = 1; i <= 2; i++) { let pdfInvoice_sub_template = [ {text: '{i}', alignment: 'center'}, {text: 'invoices_sub-{i}-name', alignment: 'left'}, {text: 'invoices_sub-{i}-unit', alignment: 'center'}, ]; temp_pdfSubTemplate[i] = pdfInvoice_sub_template; jQuery.each(temp_pdfSubTemplate[i], function (key, val) { document.write(val.text = val.text.replace(/{i}/g, i) + '</br>'); }); }
pdfInvoice_sub_template
y temp_pdfSubTemplate[i]
apuntan a la misma matriz. Cuando ejecuta temp_pdfSubTemplate[i] = pdfInvoice_sub_template
, solo está copiando la referencia a la matriz original, no está creando una copia de la matriz en sí.
Eso significa que cada vez que cambie algo en temp_pdfSubTemplate[i]
, ese cambio también aparecerá en pdfInvoice_sub_template
ya que son lo mismo.
Por lo tanto, cuando hace val.text = ...
está sobrescribiendo la propiedad de text
en la plantilla original. En la próxima iteración, tendrá 1
en lugar de {i}
, por lo que el reemplazo falla y queda 1
.
Dado que desea que temp_pdfSubTemplate[i]
sea una matriz nueva y única basada en la plantilla, mi sugerencia es que cree una función de fábrica que cree esto para usted en lugar de tener un objeto predefinido.
Cambia tu código así:
function createPdfInvoice_sub_template() { return [ {text: '{i}', alignment: 'center'}, {text: 'invoices_sub-{i}-name', alignment: 'left'}, {text: 'invoices_sub-{i}-unit', alignment: 'center'}, ]; } temp_pdfSubTemplate = []; for (i = 1; i <= 2; i++) { temp_pdfSubTemplate[i] = createPdfInvoice_sub_template(); jQuery.each(temp_pdfSubTemplate[i], function (key, val) { document.write(val.text = val.text.replace(/{i}/g, i) + '</br>'); }); } console.log(temp_pdfSubTemplate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>