DEV Community

Cover image for Programação funcional e a imutabilidade: 4 maneiras de clonar objetos no JavaScript
Lais Frigério
Lais Frigério

Posted on

Programação funcional e a imutabilidade: 4 maneiras de clonar objetos no JavaScript

A imutabilidade é um princípio da Programação Funcional que se baseia em não alterar o estado dos dados.

No entanto, no JavaScript, as variáveis não-primitivas, tais como objetos e arrays, podem ser modificadas, mesmo quando declaradas utilizando a palavra reservada const.

E, para aplicar a imutabilidade usando a linguagem de programação JavaScript, vamos aprender 4 maneiras de clonar objetos ao invés de modificá-los.

Operador Spread

Com este operador podemos copiar o conteúdo de um objeto ou array para uma nova variável:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2 = { ...person1 }
person2.name = "John"

console.log(person1)
// { name: "Anne", role: { name: "Software Engineer" }}

console.log(person2)
// { name: "John", role: { name: "Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Mas este operador usa uma técnica chamada Shallow cloning que basicamente clona apenas a raiz do seu objeto para poupar processamento, e para todos os subs objetos é usado a referência do objeto principal.

Isso significa que, ao alterar a propriedade role.name do objeto person2 também vai refletir no objeto person1:

person2.role.name = "Associate Software Engineer"

console.log(person1)
// { name: "Anne", role: { name: "Associate Software Engineer" }}

console.log(person2)
// { name: "John", role: { name: "Associate Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Para resolver isso podemos usar uma técnica chamada Deep cloning que consiste em clonar tanto o objeto raiz quanto os subs:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2 = {
    ...person1,
    name: "John",
    role: { ...person1.role }
}

person2.role.name = "Associate Software Engineer"

console.log(person2)
// { name: "John", role: { name: "Associate Software Engineer" }}

console.log(person1)
// { name: "Anne", role: { name: "Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Object.assign

Com este método podemos copiar ou mesclar o conteúdo de um ou mais objetos para uma nova variável:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2 = Object.assign({}, person1)
person2.name = "John"

console.log(person1)
// { name: "Anne", role: { name: "Software Engineer" }}

console.log(person2)
// { name: "John", role: { name: "Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Mas este método também usa a técnica Shallow cloning. Portanto, é recomendado que este método seja utilizado para clonar objetos que não tenham objetos aninhados.

Object.freeze

Já este método, além de copiar o conteúdo de um objeto para uma nova variável, também deixa as propriedades congeladas, ou seja, as propriedades não podem ser modificadas:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2 = Object.freeze(person1)
person2.name = "John"

console.log(person1)
// { name: "Anne", role: { name: "Software Engineer" }}

console.log(person2)
// { name: "Anne", role: { name: "Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Mas este método também usa a técnica Shallow cloning. Portanto, mais uma vez é recomendado que este método seja utilizado apenas para clonar objetos que não tenham objetos aninhados.

JSON.stringify e JSON.parse

O método JSON.stringify() transforma um objeto JSON em uma string:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2Str = JSON.stringify(person1)
// '{"name":"Anne","role":{"name":"Software Engineer"}}'
Enter fullscreen mode Exit fullscreen mode

Já o método JSON.parse() transforma uma string JSON válida em um objeto e/ou array:

const person1 = {
    name: "Anne",
    role: {
        name: "Software Engineer"
    }
}

const person2Str = JSON.stringify(person1)
// '{"name":"Anne","role":{"name":"Software Engineer"}}'

const person2 = JSON.parse(person2Str)
person2.name = "John"
person2.role.name = "Associate Software Engineer"

console.log(person1)
// { name: "Anne", role: { name: "Software Engineer" }}

console.log(person2)
// { name: "John", role: { name: "Associate Software Engineer" }}
Enter fullscreen mode Exit fullscreen mode

Quando o método JSON.stringify() é acionado, ele transforma o conteúdo do objeto original em uma string JSON e as referências dos subs objetos são perdidas.

E ao usar o método JSON.parse() todo o objeto e/ou array é recriado em memória.

Portanto, é possível clonar objetos e/ou arrays usando os métodos stringify e parse. Mas cuidado com seu uso pois pode ocasionar problemas de desempenho.


Conhece mais maneiras de clonar objetos no JavaScript? Deixa nos comentários 👇

Top comments (0)