A palavra-chave 'const' não torna o valor imutável. O que isso significa?

85

Há a definição const em Explorando ES6, do Dr. Axel Rauschmayer:

constfunciona como let, mas a variável que você declara deve ser inicializada imediatamente, com um valor que não pode ser alterado posteriormente . […]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

e então ele escreve

Armadilha: const não torna o valor imutável

const significa apenas que uma variável sempre tem o mesmo valor, mas não significa que o valor em si é ou se torna imutável.

Estou um pouco confuso com essa armadilha. Alguém pode definir claramente o constcom essa armadilha?

Mukund Kumar
fonte
38
A explicação do MDN é clara: "A declaração const cria uma referência somente leitura para um valor. Isso não significa que o valor que contém seja imutável, apenas que o identificador da variável não pode ser reatribuído. Por exemplo, no caso de o conteúdo ser um objeto , isso significa que o próprio objeto ainda pode ser alterado . " (grifo meu)
Gerardo Furtado
4
Isso significa que se o valor for mutável (por exemplo, se for um objeto), você ainda pode alterar esse objeto (por exemplo, atualizar, adicionar, remover propriedades).
Felix Kling
2
const x = "immutable"é imutável, porque Stringé imutável. constproíbe meramente a reatribuição.
3
@ibrahimmahrir: passar uma referência (o que o JavaScript faz para objetos) não é o mesmo que passar por referência (que descreve a relação entre as ligações, o valor é irrelevante).
Felix Kling
2
@ibrahimmahrir: Sim, esse é o problema. O termo passagem por referência tem um significado muito específico .
Felix Kling

Respostas:

97

MDN resume bem:

A declaração const cria uma referência somente leitura para um valor. Isso não significa que o valor que contém seja imutável, apenas que o identificador da variável não pode ser reatribuído. Por exemplo, caso o conteúdo seja um objeto, isso significa que o próprio objeto ainda pode ser alterado.

Mais sucintamente: const cria uma ligação imutável.

Em outras palavras: const, como var, fornece um bloco mutável de memória no qual você está armazenando algo. No entanto, const determina que você deve continuar se referindo ao mesmo pedaço de memória - você não pode reatribuir a variável a um pedaço diferente de memória, porque a referência da variável é constante.

Para realmente tornar algo constante e imutável depois de declarado, você precisa usar algo como Object.freeze(). No entanto, isso é superficial e só funciona em pares de chave / valor. Congelar um objeto inteiro exige um pouco mais de esforço. Fazer isso repetidamente de forma eficaz é ainda mais desafiador. Se você realmente precisa disso, recomendo verificar algo como Immutable.js

Mike Post
fonte
20
Em termos de C: Se um normal var xfor a struct Object *x, a const xserá a struct Object *const x. O ponteiro não pode ser alterado; a coisa para a qual está apontando pode.
Processo de Fundo Monica
151

Quando você faz algo constem JavaScript, não pode reatribuir a própria variável para fazer referência a outra coisa. No entanto, a variável ainda pode fazer referência a um objeto mutável.

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

No caso de primitivas, como strings e números, consté mais simples de entender, já que você não altera os valores, mas atribui um novo valor à variável.

Candy Gumdrop
fonte
18
Essa resposta é muito melhor do que a aceita. Mais sucinto e contém código de exemplo real. (Em outras palavras, vai
direto
16

Rebinding

conste as letdeclarações controlam se as religações (também conhecidas como reatribuições) entre identificadores e valores são permitidas:

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

Imutabilidade

A imutabilidade é controlada no nível do tipo. Objecté um tipo mutável, enquanto Stringé um tipo imutável:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


fonte
1

const significa: você não pode alterar o valor atribuído inicialmente.

Primeiro, defina o que é um valor em js. O valor pode ser: Booleanos, strings, números, objetos, funções e valores indefinidos.

Tipo: As pessoas estão chamando você pelo seu nome, não está mudando. No entanto, você muda de roupa. A ligação entre as pessoas e você é o seu nome. O resto pode mudar. Desculpe pelo exemplo estranho.

Então, deixe-me dar alguns exemplos:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

Como você pode ver, a menos que não altere o "primeiro" valor atribuído a const, não há erro. Sempre que você tenta alterar o primeiro valor atribuído para outra coisa, ele fica irritado e dá um erro.

Portanto, esta é a segunda coisa que você deve saber ao usar const. Ou seja, ele deve ser inicializado com um valor em sua declaração ou ficará zangado.

const orphan;                    // error
const rich = 0;                  // no error
Inanc Gumus
fonte
0

ES6/ ES2015 constpalavra-chave:

A constpalavra-chave é usada para declarar uma variável com escopo de bloco (como declarar com let). A diferença entre declarar uma variável com conste leté a seguinte:

  1. Uma variável declarada constnão pode ser reatribuída .
  2. Uma variável declarada com constdeve ser atribuída quando declarada . Esta é uma consequência lógica do ponto anterior porque uma variável declarada com constnão pode ser reatribuída, é por isso que temos que atribuí-la exatamente uma vez quando declaramos a variável .

Exemplo:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

No exemplo acima, podemos observar o seguinte:

  1. A variável myVariabledeclarada com letpode primeiro ser declarada e depois atribuída.
  2. A variável myConstantdeclarada com constdeve ser declarada e atribuída ao mesmo tempo.
  3. Quando tentamos reatribuir a variável myConstant, obtemos o seguinte erro:

TypeError não capturado: atribuição a variável constante

Advertência: a variável atribuída com constainda é mutável:

Uma variável declarada com constsimplesmente não pode ser reatribuída, ainda é mutável . Ser mutável significa que a estrutura de dados (objeto, array, mapa, etc) que foi atribuída à constvariável ainda pode ser alterada (ou seja, mutada). Exemplos de mutação são:

  1. Adicionar / excluir / alterar uma propriedade de um objeto
  2. Alterar o valor de uma matriz em um índice de matriz específico

Se realmente quiser que um objeto não seja mutável, você terá que usar algo como Object.freeze(). Este é um método que congela um objeto. Um objeto congelado não pode mais ser alterado e nenhuma nova propriedade pode ser adicionada.

Exemplo:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

Willem van der Veen
fonte