Objetos Constantes: Proibição de Alterações no Objeto - JavaScript
O idioma JavaScript nos permite alterar dinamicamente as propriedades dos objetos, adicionar novas propriedades e métodos ou remover os existentes. No entanto, tais alterações podem ser indesejáveis. Para isso, JavaScript oferece três mecanismos:
Proibição da expansão de objetos
Selagem de objetos
Congelamento de objetos
Proibição da Expansão de Objetos
O método Object.preventExtensions()
Object.preventExtensions()
Primeiro, vamos ver um exemplo onde adicionamos uma nova propriedade com sucesso:
const tom = {name: "Tom"};
// adicionando uma nova propriedade - company
tom.company = "Localhost";
console.log(`Name: ${tom.name} Company: ${tom.company}`); // Name: Tom Company: Localhost
Aqui, uma nova propriedade company
tom
Agora, vamos proibir a expansão aplicando o método Object.preventExtensions()
const tom = {name: "Tom"};
Object.preventExtensions(tom); // proibindo a expansão do objeto tom
tom.company = "Localhost"; // tentando adicionar uma nova propriedade ao objeto tom
console.log(`Name: ${tom.name} Company: ${tom.company}`); // Name: Tom Company: undefined
Como resultado, mesmo que tentemos definir uma nova propriedade, ela não será adicionada. Ao tentar acessar tal propriedade, obtemos undefined
Às vezes, pode ser necessário determinar se um objeto é expansível. Para verificar a expansibilidade, você pode usar o método Object.isExtensible()
true
false
const tom = {name: "Tom"};
console.log(Object.isExtensible(tom)); // true
Object.preventExtensions(tom); // proibindo a expansão do objeto tom
console.log(Object.isExtensible(tom)); // false
Selagem de Objetos
A selagem, ou "sealing", de objetos também permite proibir a expansão dos objetos. Além disso, proíbe a alteração das configurações das propriedades já existentes. O método Object.seal()
Primeiro, vamos ver o que podemos fazer com um objeto antes de aplicar Object.seal()
const tom = {name: "Tom"};
// tornando a propriedade name não editável
Object.defineProperty(tom, "name", {writable: false});
tom.name = "Tomas";
// adicionando uma nova propriedade - age
tom.age = 39;
console.log(`Name: ${tom.name} Age: ${tom.age}`); // Name: Tom Age: 39
// permitindo a edição da propriedade name novamente
Object.defineProperty(tom, "name", { writable: true});
tom.name = "Tomas";
console.log(`Name: ${tom.name} Age: ${tom.age}`); // Name: Tomas Age: 39
const tom = {name: "Tom"};
// tornando a propriedade name não editável
Object.defineProperty(tom, "name", {writable: false});
tom.name = "Tomas";
// adicionando uma nova propriedade - age
tom.age = 39;
console.log(`Name: ${tom.name} Age: ${tom.age}`); // Name: Tom Age: 39
// permitindo a edição da propriedade name novamente
Object.defineProperty(tom, "name", { writable: true});
tom.name = "Tomas";
console.log(`Name: ${tom.name} Age: ${tom.age}`); // Name: Tomas Age: 39
Agora, aplicaremos o método Object.seal()
const tom = {name: "Tom"};
Object.seal(tom); // selando o objeto tom, impedindo a expansão e alteração de configurações
// tentando tornar a propriedade name não editável
Object.defineProperty(tom, "name", {writable: false});
tom.name = "Tomas";
// tentando adicionar uma nova propriedade - age
tom.age = 39;
console.log(`Name: ${tom.name} Age: ${tom.age}`); // Name: Tom Age: undefined
// tentando permitir a edição da propriedade name novamente
Object.defineProperty(tom, "name", {writable: true}); // Uncaught TypeError: Cannot redefine property: name
Após selar o objeto com Object.seal(tom)
tom.age
undefined
Object.defineProperty()
Para verificar se um objeto está selado, podemos usar o método Object.isSealed()
true
Object.isExtensible()
false
Proibição de Alteração dos Valores das Propriedades
O congelamento, ou freezing, permite proibir a alteração dos valores das propriedades, tornando o objeto completamente constante. Por exemplo, simplesmente definir um objeto como uma constante comum usando o operador const
const tom = {name: "Tom"};
tom.name= "Tomas";
console.log(tom.name); // Tomas
Aqui, vemos que o valor da propriedade do objeto mudou, embora o objeto seja definido como uma constante.
O operador const
const tom = {name: "Tom"{;
tom = {name: "Sam"{; // Erro - não é possível atribuir um novo valor à constante novamente
No entanto, podemos alterar os valores das propriedades do objeto.
Para tornar um objeto verdadeiramente constante, é necessário aplicar o método especial Object.freeze()
const tom = {name: "Tom"};
Object.freeze(tom);
tom.name= "Tomas"; // o valor da propriedade não pode ser alterado
console.log(tom.name); // Tom
Para verificar se os valores das propriedades de um objeto podem ser alterados, usa-se o método Object.isFrozen()
true
const tom = {name: "Tom"};
console.log(Object.isExtensible(tom)); // true
console.log(Object.isSealed(tom)); // false
console.log(Object.isFrozen(tom)); // false
Object.freeze(tom);
console.log(Object.isExtensible(tom)); // false
console.log(Object.isSealed(tom)); // true
console.log(Object.isFrozen(tom)); // true
É importante notar que um objeto "congelado" é o grau extremo de proibição de alterações em um objeto. Assim, tal objeto é não expansível, e também não é possível alterar a configuração de suas propriedades.