como se muestra arriba, el operador spread es útil para crear nuevas instancias de matrices que no se comportan inesperadamente debido a referencias antiguas. Por lo tanto, el operador spread es útil para agregar a una matriz en estado React.
Foto por Donald Giannatti en Unsplash
copia Superficial de usar .slice ()
2.,Para las matrices específicamente, el uso de la incorporada en el .slice()
método funciona de la misma como la propagación del operador — la creación de una copia superficial de un nivel:
Foto de Antonio García en la Unsplash
copia Superficial de usar .assign ()
3.,El mismo tipo de copia superficial podría ser creados usando Object.assign()
, que puede ser utilizado con cualquier objeto o array:
Foto por Paweł Czerwiński en Unsplash
copia Superficial utilizando matrices Matriz.desde ()
4.,Otro método para copiar una matriz JavaScript es usar Array.from()
, que también hará una copia superficial, como se muestra en este ejemplo:
Si un objeto o matriz contiene matrices, copias superficiales funcionarán inesperadamente, porque los objetos anidados no son en realidad clonados.
para objetos anidados profundamente, se necesitará una copia profunda. Explico por qué a continuación.,
Foto por brabus biturbo en Unsplash
Reloj hacia fuera para la anidadas Gotcha!
por otro lado, cuando los objetos JavaScript que incluyen matrices están profundamente anidados, el operador spread solo copia el primer nivel con una nueva referencia, pero los valores más profundos todavía están vinculados entre sí.,
Para resolver este problema requiere la creación de una copia en profundidad, en contraposición a una copia superficial. Se pueden hacer copias profundas usando lodash, rfdc, o el método R. clone() de la biblioteca de programación funcional Ramda. Exploraré copias profundas a continuación.
Foto por Landon Martin en Unsplash
¿Qué es una copia profunda?,
para los objetos y matrices que contienen otros objetos o matrices, copiar estos objetos requiere una copia profunda. De lo contrario, los cambios realizados en las referencias anidadas cambiarán los datos anidados en el objeto o matriz original.
esto se compara con una copia superficial, que funciona bien para un objeto o matriz que contiene solo valores primitivos, pero fallará para cualquier objeto o matriz que tenga referencias anidadas a otros objetos o matrices., la diferencia entre ==
y ===
puede ayudar a ver visualmente la diferencia entre superficial y profunda de copia, como el operador de igualdad estricta (===
), muestra que las referencias anidadas son los mismos:
Foto mya thet khine en Unsplash
copia Profunda con lodash
1.,La biblioteca lodash es la forma más común en que los desarrolladores de JavaScript hacen una copia profunda. Es sorprendentemente fácil de usar:
Lodash que proviene el nombre de la biblioteca que se hace referencia como un carácter de subrayado (_
), un «guión bajo» o lodash para el corto.
Foto de Annie Spratt en Unsplash
copia Profunda con Ramda
2.,La biblioteca de programación funcional Ramda incluye el método R.clone()
, que hace una copia profunda de un objeto o matriz.
tenga en cuenta que R.clone()
desde Ramda es equivalente a _.cloneDeep()
para lodash, como Ramda no tiene una copia superficial método auxiliar.,
Foto por Roi Dimor en Unsplash
copia Profunda con la función personalizada
3. Es bastante fácil escribir una función JavaScript recursiva que hará una copia profunda de objetos anidados o matrices. He aquí un ejemplo:
tenga en cuenta que también tengo que comprobar el valor null ya que el typeof
null es «objeto.,»
Foto por Scott Webb en Unsplash
copia Profunda con JSON.analizar / stringify
4. Si sus datos se ajustan a las especificaciones (consulte a continuación), JSON.parse
seguido de JSON.stringify
copiará profundamente su objeto.,tipos plex dentro de su objeto, un liner muy simple para clonar profundamente un objeto es: JSON.parse(JSON.stringify(object))
» — Dan Dascalescu en su respuesta StackOverflow
para demostrar algunas razones por las que este método no se recomienda generalmente, aquí hay un ejemplo de creación de una copia profunda usando JSON.parse(JSON.stringify(object))
:
una función personalizada o las bibliotecas mencionadas pueden hacer una copia profunda sin necesidad de preocuparse por el tipo de contenido, aunque las referencias circulares los dispararán a todos.,
Next I discuss a blazing-fast library called rfdc
that can handle circular references while being as fast as a custom deep copy function.
Photo by Scott Webb on Unsplash
Really fast deep copy? Think rfdc
5.,622333″>
«rdfc
clones all JSON types: •Object
•Array
•Number
•String
•null
With additional support for: •Date
(copied) •undefined
(copied) •Function
(referenced) •AsyncFunction
(referenced) •GeneratorFunction
(referenced) •arguments
(copied to a normal object)
All other types have output values that match the output of JSON.parse(JSON.stringify(o))
.,»—rfdc Documentation
Usando rfdc
es bastante sencillo, al igual que las otras bibliotecas:
la biblioteca rfdc
admite todos los tipos y también admite referencias circulares con un indicador opcional que disminuye el rendimiento en aproximadamente un 25%.
Las referencias circulares romperán los otros algoritmos de copia profunda discutidos.,
una biblioteca de este tipo sería útil si se trata de un objeto grande y complejo, como uno cargado desde archivos JSON de 3MB a 15MB de tamaño.,e Las copias superficiales son las más rápidas, seguidas por las copias profundas usando una función personalizada o rfdc
:
«copia profunda por rendimiento: clasificada de mejor a peor
reasignación «=
» (matrices de cadenas, matrices de números — solo)
slice (string arrays, number arrays — only)
concatenación (string arrays, number arrays — only)
función personalizada: for-loop o copia recursiva
jQuery $.extend
JSON.parse
(string arrays, number arrays, object arrays — only)
underscore.,js _.clone
(string arrays, number arrays — only)
Lo-Dash _.cloneDeep
» — Tim Montague en su respuesta StackOverflow
Usando JSON.parse
/JSON.stringify
crea problemas en torno a los tipos de datos, por lo que se recomienda rfdc
, a menos que desee escribir una función personalizada.,
Foto por Keila Hötzel en Unsplash
Conclusión
en realidad, es bastante fácil de evitar la necesidad de copia profunda en JavaScript — si sólo se puede nunca nido de objetos y arrays dentro de la otra.,
porque en ese caso — donde no hay anidamiento y los objetos y matrices solo contienen valores primitivos — hacer una copia superficial con el operador spread (…
), .slice()
, y .assign()
todo funciona muy bien.
pero, en el mundo real, donde los objetos tienen matrices dentro de ellos, o viceversa, entonces se necesitará usar una copia profunda. Recomiendo rfdc
para Clones profundos.,
(tenga en cuenta que algunos también pueden sugerir el uso de JSON.stringify()
seguido de JSON.parse()
, pero esa no es una forma confiable de hacer una copia profunda.)
Ahora sal y copia en profundidad algunos objetos anidados!
Foto de Kristina Evstifeeva en Unsplash
leer Más
Cocodrilo.,io tiene un gran artículo sobre clonación profunda usando lodash:
Samantha Ming explica las copias superficiales y profundas en dev.to:
El artículo de Peter Tasker sobre dev.,para generar muchos comentarios, incluyendo una explicación de cuando JSON.parse(JSON.stringify(obj))
falla:
James Dorr cubre la necesidad de copiar cuando se agrega a un array a React State (ya que React State es inmutable) en JavaScript en Inglés sencillo:
Ramón Miklus usa immutability-helper, una biblioteca utilizada para mantener la inmutabilidad de los datos, en lugar de lodash a deep copy en Codementor:
hablando de inmutabilidad, Gabriel Lebec tiene una gran guía en dev.,to:
Photo by 青 晨 on Unsplash