자바 스크립트에서 상수 값을 변경할 수있는 이유


102

ES6가 아직 표준화되지 않았다는 것을 알고 있지만 현재 많은 브라우저 const 가 JS에서 키워드를 지원 합니다.

사양에서 다음과 같이 작성되었습니다.

상수의 값은 재 할당을 통해 변경할 수 없으며 상수를 다시 선언 할 수 없습니다. 이 때문에 초기화하지 않고 상수를 선언 할 수 있지만 그렇게하는 것은 쓸모가 없습니다.

그리고 이렇게하면 :

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];

나는 모든 것이 괜찮 볼 xxx여전히 6하고 yyy있다 [].

그러나 그렇게 yyy.push(6); yyy.push(1);하면 내 상수 배열이 변경되었습니다. 지금 [6, 1]은 그렇고 나는 여전히 yyy = 1;.

이건 버그인가요, 아니면 뭔가 빠졌나요? 나는 최신 크롬과 FF29에서 그것을 시도했다


1
클래스를 만들고, 변수를 선언하고, 클래스 내부에 값을 할당 할 수 있습니다. 그런 다음 해당 변수에 대한 GETTER를 만듭니다. 세터를 구현하지 마십시오. 상수를 구현해야합니다 ...
Andrew

8
@Andrew는 감사하지만 어떻게 할 수 있는지 묻지 않습니다. const 키워드가 이런 식으로 작동하는 이유가 궁금합니다.
Salvador Dali

답변:


174

문서는 다음과 같이 설명합니다.

... 상수는 재 할당을 통해 변경할 수 없습니다
... 상수는 다시 선언 할 수 없습니다.

배열이나 객체에 추가 할 때 상수를 재 할당하거나 다시 선언하는 것이 아니라 이미 선언되고 할당 된 것이며 상수가 가리키는 "목록"에 추가하는 것입니다.

따라서 이것은 잘 작동합니다.

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

x.foo = 'bar2';

console.log(x); // {foo : 'bar2'}  

이:

const y = [];

y.push('foo');

console.log(y); // ['foo']

y.unshift("foo2");

console.log(y); // ['foo2', 'foo']

y.pop();

console.log(y); // ['foo2']

하지만 둘 다 :

const x = {};
x = {foo: 'bar'}; // error - re-assigning

const y = ['foo'];
const y = ['bar']; // error - re-declaring

const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared

4
그래서 이것이 버그는 아니지만 이런 식으로 작동해야한다는 뜻입니까? 상수에 대한 생각은 바꿀 수 없다고 생각했기 때문입니다. 기본적으로 프로그래머는 무슨 일이 일어나더라도 내 상수 내부의 값을 변경할 수 없다고 신뢰합니다.
Salvador Dali

2
나는 그것이 그렇게 쉽지 않다고 생각한다.이 경우 상수의 값은 특정 요소의 배열이다. 아무것도 변경하면 이 변경 됩니다.
veritas 2014 년

6
예,이 방식으로 작동해야합니다. 상수를 재 할당하는 것이 아니라 여전히 동일한 참조입니다. 배열에 상수 참조를 추가하고 배열과 객체는 "목록"과 같습니다. 참조를 변경하거나 상수를 다시 선언하지 마십시오.
adeneo

27
@SalvadorDali : 상수읽기 전용 은 서로 다른 두 가지입니다. 변수는 상수 이지만 가리키는 배열은 읽기 전용이 아닙니다
Matt Burland 2014 년

46

이것은 상수가 실제로 배열에 대한 참조 를 저장하기 때문에 발생합니다 . 배열에 무언가를 결합 할 때 상수 값을 수정하는 것이 아니라 가리키는 배열을 수정하는 것입니다. 객체를 상수에 할당하고 그 속성을 수정하려는 경우에도 마찬가지입니다.

수정할 수 없도록 배열 또는 개체를 고정하려면 Object.freeze이미 ECMAScript 5의 일부인 메서드를 사용할 수 있습니다 .

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]

1
같은 논리 five로 5로 설정된 상수 는 실제로 5의 값이 아니라 숫자 5에 대한 참조 일뿐입니다. 따라서 five++변경하면 상수가 가리키는 숫자 만 변경됩니다.
Anthony

3
@Anthony 기준 것은 단지 배열과 객체, 원시적하지 값을 작동
Guilherme Sehn

1
@Anthony 예에서 변수가 five가리키는 숫자를 변경합니다 (변수 five는 숫자 5의 레이블 이었지만 이제는 다른 숫자 인 6을 가리 킵니다). 질문의 예 (및이 답변)에서 x항상 동일한 목록을 가리 킵니다. xconst 이면 다른 목록을 가리킬 수 없습니다. 유일한 차이점은 동일한 목록이 늘어나거나 줄어들 수 있다는 것입니다. 이것은 기본 요소가 아닌 배열과 객체에 대해서만 가능합니다.
ShreevatsaR

9

이것은 내가 생각할 수있는 모든 프로그래밍 언어에서 일관된 동작입니다.

C를 고려하십시오-배열은 단지 영광스러운 포인터입니다. 상수 배열은 포인터의 값이 변경되지 않음을 의미 할뿐입니다. 실제로 해당 주소에 포함 된 데이터는 자유롭게 사용할 수 있습니다.

자바 스크립트에서는 상수 객체의 메소드를 호출 할 수 있습니다 (물론-그렇지 않으면 상수 객체가 그다지 목적을 이루지 않습니다!) 이러한 메소드는 객체를 수정하는 부작용이있을 수 있습니다. 자바 스크립트의 배열은 객체이기 때문에이 동작은 그들에게도 적용됩니다.

당신이 확신하는 것은 상수가 항상 같은 객체를 가리킬 것이라는 것입니다. 개체 자체의 속성은 자유롭게 변경할 수 있습니다.


4

const 선언은 값에 대한 읽기 전용 참조를 만듭니다. 보유한 값이 변경 불가능하다는 의미가 아니라 변수 식별자를 재 할당 할 수 없다는 의미입니다. 예를 들어 콘텐츠가 객체 인 경우 이는 객체의 내용 (예 : 매개 변수)이 변경 될 수 있음을 의미합니다.

또한 중요한 참고 사항 :

전역 상수는 창 개체의 속성이되지 않습니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const


3

https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 문제에 대해 더 명확하게 설명 할 수 있다고 생각합니다 .

기본적으로 const항상 메모리에서 동일한 주소를 가리키는 것으로 요약됩니다 . 해당 주소에 저장된 값을 변경할 수 있지만 const가리키는 주소도 변경할 수 없습니다 .

const언급 한 정의 const는가 원시 값을 보유하는 주소를 가리킬 때 참 입니다. 이것은 const주소를 변경하지 않고 는 값을 할당 할 수없고 (기본 값 할당이 작동하는 방식이기 때문에) a의 주소를 변경할 const수 없기 때문입니다.

const가 원시 값이 아닌 값을 가리키는 것처럼 주소 값을 편집 할 수 있습니다.


2

이 기사를 통해 객체를 .zip으로 정의한 후에도 업데이트 할 수 있었던 이유를 검색했습니다 const. 따라서 여기서 요점은 직접 Object가 아니라 업데이트 할 수있는 속성이 포함되어 있다는 것입니다.

예를 들어, 내 개체는 다음과 같습니다.

const number = {
    id:5,
    name:'Bob'
};

위의 답변은 속성이 아닌 const 인 Object임을 올바르게 지적했습니다. 따라서 다음을 수행하여 ID 또는 이름을 업데이트 할 수 있습니다.

number.name = 'John';

그러나 다음과 같이 개체 자체를 업데이트 할 수 없습니다.

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.

1
귀하의 예는 실용적이고 올바른 설명입니다
Ebrahim

0

const에서 객체의 값을 변경할 수 있으므로 객체는 실제로 할당 데이터를 저장하지 않고 대신 해당 데이터를 가리 킵니다. 따라서 Javascript의 기본 요소와 객체에는 차이가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.