Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Mudança na data usando _data

Olá,

Conforme mostrado no vídeo sobre programação defensiva, para evitar a alteração na propriedade data eu posso usar:

return new Date(this._data.getTime());
e
this._data = new Date(data.getTime());

Se eu executar n1.data.setDate(10) a data não será alterada, mas se eu executar n1._data.setDate(10) a alteração ocorrerá. É isso mesmo, certo? Como eu poderia evitar isso?

3 respostas

Oi Marcos, aí complicou. Evitar fica dificil por conta da falta de visibilidade das variáveis no javascript. Então, por mais que você retorne algo novo, se o programador quiser a referência original ele pode fazer besteira.

solução!

Existem algumas opções...

A mais simples na minha opinião são closures:

function createPerson(name) {

  const Person = {
    getName: function(){
      return name
    },

    setName: function(newName){
      name = newName
    }
  }

  return Person
}

const joao = createPerson('João da Silva')

// joao não tem propriedade name
// você está criando ela agora, mas não importa,
// os métodos getters e setters não acessam essa propriedade
joao.name = 'Jose'
console.log(joao.getName()) // 'João da Silva'
console.log(joao)
//{
//  getName: //...
//  name: "Jose",
//  setName: //...
//}
joao.setName('Ricardo')
console.log(joao.getName()) // 'Ricardo'

const maria = createPerson('Maria de Souza')
maria.name = 'Marinalva'
console.log(maria.getName())
console.log(maria)

A função retorna um objeto, este objeto não tem a propriedade nome, na verdade foi criada uma closure. Você não consegue de fora alterar o nome.

Um impacto disso é que você não se beneficia dos protótipos, simplesmente cria um novo objeto que tem aqueles métodos. Já com protótipos (classes em js usam protótipos) um objeto acessa o método de outro, ou seja, você não tem várias cópias daquele método. Protótipos te ajudam a poupar memória.

O padrão acima se chama factory function.

Também é possível utilizar a closure na classe, mas você teria que criar seus métodos dentro do construtor, o que daria na mesma que usar factory functions (cada nova instância teria sua própria cópia dos métodos), você pode ver um exemplo nesta resposta do StackOverflow.

Há uma maneira para se introduzir privacidade nas classes utilizando WeakMaps, ainda não utilizei, não tenho certeza absoluta se é possível acessar de fora, mas a princípio parece promissor, você pode dar uma olhada aqui. O artigo do link anterior também menciona uma maneira utilizando o novo tipo do JavaScript Symbol() porém existe uma maneira de acessar.

Entendi cara, muito obrigado pela ajuda! Vou pesquisar estes links.