Object.freeze () vs const

136

Object.freeze()parece ser um método de conveniência de transição para avançar no uso constno ES6.

Existem casos em que ambos ocorrem no código ou há uma maneira preferida de trabalhar com dados imutáveis?

Devo usar Object.freeze()até o momento todos os navegadores com os quais trabalho com suporte conste mudar para o uso const?

Sergei Basharov
fonte
2
Eu comecei a usar babeljs no meu processo de compilação para poder ignorar principalmente problemas de compatibilidade como esses.
spender
22
Não - eles fazem coisas diferentes. const impede a reatribuição (por exemplo, você não pode const x = 1; x = 2); o congelamento impede a mutação (por exemplo, você não pode Object.freeze (x); xa = 2);
joews
Não tenho certeza se faz sentido fazer disso uma nova pergunta ou apenas colocá-la aqui, mas também ficaria curioso se houver grandes diferenças entre Symbols e Object.freeze? Eu sinto que eles também estão relacionados (ou seja, símbolos são avaliados como congelados do Object.isFrozenmas eles também são o seu próprio tipo de dados primitivo ...)
aug
1
A mutação é evitada apenas para o primeiro nível, portanto você não pode Object.freeze (x); xa = 2, mas você pode Object.freeze (x); xab = 2. Consulte jsfiddle.net/antimojv/op6ea91w/8 . Para um congelamento completo, use as bibliotecas ad hoc
Antimo

Respostas:

232

conste Object.freezesão duas coisas completamente diferentes.

constaplica-se a ligações ("variáveis"). Ele cria uma ligação imutável, ou seja, você não pode atribuir um novo valor à ligação.

Object.freezetrabalha com valores e, mais especificamente, valores de objetos . Torna um objeto imutável, ou seja, você não pode alterar suas propriedades.

Felix Kling
fonte
3
Basicamente, consté o novo var; é apenas de escopo de bloco e impede a reatribuição. Você pode usar let, mas realmente só precisa, se quiser alterar o valor que uma variável aponta, o que faz sentido para variáveis ​​de controle / iterador de loop e tipos simples como números e strings, mas não para a maioria dos usos de objetos (incluindo matrizes). Se você deseja um objeto / array cujo conteúdo não possa ser alterado, além de declará- constlo, também deve chamá Object.freeze()-lo.
Re
2
constNÃO é o novo var, leté o novovar
Facundo Colombier
84

No ES5 Object.freeze, não funciona em primitivas, que provavelmente seriam mais comumente declaradas usando do constque objetos. Você pode congelar primitivos no ES6, mas também possui suporte para const.

Por outro lado, constusado para declarar objetos não os "congela", você não pode redeclarar todo o objeto, mas pode modificar suas chaves livremente. Por outro lado, você pode redeclarar objetos congelados.

Object.freeze também é superficial, então você precisa aplicá-lo recursivamente em objetos aninhados para protegê-los.

var ob1 = {
   foo : 1,
    bar : {
        value : 2   
    }
};
Object.freeze( ob1 );

const ob2 = {
   foo : 1,
    bar : {
        value : 2   
    }
}

ob1.foo = 4;  // (frozen) ob1.foo not modified
ob2.foo = 4;  // (const) ob2.foo modified

ob1.bar.value = 4;  // (frozen) modified, because ob1.bar is nested
ob2.bar.value = 4;  // (const) modified

ob1.bar = 4;  // (frozen) not modified, bar is a key of obj1
ob2.bar = 4;  // (const) modified

ob1 = {};  // (frozen) ob1 redeclared
ob2 = {}; // (const) ob2 not redeclared
pawel
fonte
Essa explicação esclareceu muitas das minhas perguntas de uma só vez! Em relação a ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: É por causa do escopo do método?
YCode 23/03
14

Resumo:

conste Object.freeze()servir a propósitos totalmente diferentes.

  • constexiste para declarar uma variável que precisa ser atribuída imediatamente e não pode ser reatribuída. variáveis ​​declaradas por consttêm escopo de bloco e não funcionam como escopo de variáveis ​​declaradas comvar
  • Object.freeze()é um método que aceita um objeto e retorna o mesmo objeto. Agora, o objeto não pode ter suas propriedades removidas ou novas propriedades adicionadas.

Exemplos const:

Exemplo 1: Não é possível reatribuir const

const foo = 5;

foo = 6;

O código a seguir gera um erro porque estamos tentando reatribuir a variável foo que foi declarada com a constpalavra - chave, não podemos reatribuí-la.

Exemplo 2: Estruturas de dados às quais são atribuídos constpodem ser mutadas

const object = {
  prop1: 1,
  prop2: 2 
}

object.prop1 = 5;   // object is still mutable!
object.prop3 = 3;   // object is still mutable!

console.log(object);  // object is mutated

Neste exemplo, declaramos uma variável usando a constpalavra - chave e atribuímos um objeto a ela. Embora não possamos reatribuir a essa variável chamada objeto, podemos alterar o próprio objeto. Se alterarmos as propriedades existentes ou adicionarmos novas, isso terá efeito. Para desativar qualquer alteração no objeto que precisamos Object.freeze().

Exemplos Object.freeze():

Exemplo 1: Não é possível alterar um objeto congelado

object1 = {
  prop1: 1,
  prop2: 2
}

object2 = Object.freeze(object1);

console.log(object1 === object2); // both objects are refer to the same instance

object2.prop3 = 3; // no new property can be added, won't work

delete object2.prop1; // no property can be deleted, won't work

console.log(object2); // object unchanged

Neste exemplo, quando chamamos Object.freeze()e apresentamos object1como argumento, a função retorna o objeto que está agora 'congelado'. Se compararmos a referência do novo objeto com o objeto antigo usando o ===operador, podemos observar que eles se referem ao mesmo objeto. Além disso, quando tentamos adicionar ou remover propriedades, podemos ver que isso não tem nenhum efeito (gerará erro no modo estrito).

Exemplo 2: Objetos com referências não estão totalmente congelados

const object = {
  prop1: 1,
  nestedObj: {
    nestedProp1: 1,
    nestedProp2: 2,
  } 
}


const frozen = Object.freeze(object);

frozen.prop1 = 5; // won't have any effect
frozen.nestedObj.nestedProp1 = 5; //will update because the nestedObject isn't frozen

console.log(frozen);

Este exemplo mostra que as propriedades de objetos aninhados (e outras por estruturas de dados de referência) ainda são mutáveis . Portanto Object.freeze(), não 'congela' completamente o objeto quando ele possui propriedades que são referências (por exemplo, Arrays, Objetos).

Willem van der Veen
fonte
12
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

O exemplo acima torna completamente seu objeto imutável.

Vamos olhar o exemplo a seguir.

const obj = {
  a: 1,
  b: 2
};
obj.a = 13; // You can change a field
obj.newField = 3; // You can assign new field.

Não dará nenhum erro.

Mas se você tentar assim

const obj = {
      a: 1,
      b: 2
    };
obj = {
 t:4
};

Irá gerar um erro como "obj é somente leitura".

Outro caso de uso

const obj = {a:1};
var obj = 3;

Vai jogar Duplicate declaration "obj"

Também de acordo com a explicação const do mozilla docs

A declaração const cria uma referência somente leitura para um valor. Isso não significa que o valor que ele possui é imutável , apenas que o identificador da variável não pode ser reatribuído.

Estes exemplos criados de acordo com os recursos do babeljs ES6.

İlker Korkut
fonte
4

Sejamos simples.

Eles são diferentes. Verifique os comentários no código, que explicarão cada caso.

Const- É uma variável de escopo de bloco como let, cujo valor não pode ser reatribuído, declarado novamente.

Que significa

{
 const val = 10;  // you can not access it outside this block, block scope variable

}

console.log(val); // undefined because it is block scope 

const constvalue = 1;
constvalue = 2; // will give error as we are re-assigning the value;
const obj = { a:1 , b:2};

obj.a = 3;
obj.c = 4;
console.log(obj); // obj = {a:3,b:2,c:4} we are not assigning the value of identifier we can 
                  // change the object properties, const applied only on value, not with properties
obj = {x:1};     // error you are re-assigning the value of constant obj 
obj.a = 2 ;     // you can add, delete element of object

Todo o entendimento é que const é um escopo de bloco e seu valor não é reatribuído.

Object.freeze: As propriedades raiz do objeto são imutáveis, também não podemos adicionar e excluir mais propriedades, mas podemos reatribuir o objeto inteiro novamente.

var x = Object.freeze({data:1,
    name:{
    firstname:"hero", lastname:"nolast"
    }
});

x.data = 12;  // the object properties can not be change but in const you can do
x.firstname ="adasd"; // you can not add new properties to object but in const you can do

x.name.firstname = "dashdjkha"; // The nested value are changeable 

//The thing you can do in Object.freeze but not in const

x = { a: 1};  // you can reassign the object when it is Object.freeze but const its not allowed

// Uma coisa semelhante em ambas é que objetos aninhados são mutáveis

const obj1 = {nested :{a:10}};
var obj2 =  Object.freeze({nested :{a:10}});

obj1.nested.a = 20; // both statement works
obj2.nested.a = 20;

Obrigado.

Himanshu sharma
fonte