부트캠프 그룹 슬랙에 어떤 분이 흥미로운 질문을 올려주셨다.
흠 scope에 대해 질문있습니다.
block scope 중 let과 const는 재선언이 안된다고 하는데let x = 2; < undefined let x = 3; < undefined const x = 4; < VM742:1 Uncaught SyntaxError: Identifier 'x' has already been declared const y = 1; < undefined let y = 1; < VM824:1 Uncaught SyntaxError: Identifier 'y' has already been declared
개발자코드를 돌려보니 let은 재선언이 되고 const는 안되는데 재선언 규칙을 잘 모르겠습니다.
나도 처음엔 단순 scope 문제인줄 알고 scope 위주로 검색을 했었는데, 정답은 콘솔 모드였다!
일반 스크립트 실행과 "콘솔 모드"(e.g. 크롬 개발자 도구의 콘솔) 간에는 차이가 있습니다. 전자는 자바스크립트 표준 문법을 따릅니다. 모든 자바스크립트 엔진(자바스크립트를 해석하여 실행하는 도구)은 이를 따라야 하며, 자바스크립트 표준에 맞지 않는 것은 버그로 처리해야 합니다. 그러나 후자는.. 자바스크립트 표준 문법에 따라야 하는 것이 맞지만, 콘솔 모드(=REPL 모드)의 interactive한 특징 때문에 문법적인 면에서 아주 약간의 차이가 있습니다.
let
변수를 재선언하는 것은 일반적인 스크립트에서는 에러를 발생시킵니다. 그러나 개발자 도구 콘솔에서는 이를 무시합니다.
다음의 상황을 볼까요?
> let a = 42j; // 42라는 숫자를 입력하려고 했는데 실수로 42j라고 입력해버렸다!
< Uncaught SyntaxError: Invalid or unexpected token
> let a = 42; // 아오;; 다시 선언&할당해야지
< Uncaught SyntaxError: 'a' has already been declared (=님 이미 a 선언했는데 왜 또 선언함? 에러빵!!!!)
> // 나: 아니 에러났길래 변수 선언 안된줄 알았지...ㅠㅜ
let a = 42j
를 선언했을 때 에러가 났음에도 불구하고 해당 a
변수를 다시 선언할 수 없는 상태가 되어버렸습니다. 오타 한번 나면 해당 변수는 사용할 수 없게 되는 것입니다.
그래서 크롬은 크롬 개발자 도구 콘솔에 let
변수 재선언에 대한 특별한 예외케이스를 하나 만들었습니다. 바로 다음과 같이요!
> let a; let a; // 한 줄에 재선언하는 경우에는 재선언 안됨!
< Uncaught SyntaxError: Identifier 'a' has already been declared
> let a;
> let a; // 다른 줄에서 재선언하는 건 괜춘괜춘.
한 줄에서 재선언을 하는 경우에는 자바스크립트 표준 문법에 따라 에러를 뱉지만, 다른 줄에 재선언 하는 경우에는 에러를 발생시키지 않습니다.
자바스크립트 표준 문법 상 let과 const 모두 재선언을 하면 에러를 내는 것이 맞습니다. 이 예외는 개발자 도구 콘솔에만 적용된다는 점 잊지마세요!
또한 구글 개발자 도구 콘솔에서는 변수의 종류(var
, let
, const
)를 바꿔서 재선언하지 못하도록 해놨다고 합니다.
결론적으로 이렇게 됩니다.
> var g;
> var g; // 원래 var는 재선언이 가능하니 에러x
> let g; // 다른 종류로 재선언했으므로 에러 발생
> const g; // 다른 종류로 재선언했으므로 에러 발생
> let h;
> let h; // (1)의 케이스처럼 다른 줄에서 재선언했으므로 에러x
> const h; // 다른 종류로 재선언했으므로 에러 발생
> var h; // 다른 종류로 재선언했으므로 에러 발생
> const i = 1;
> const i = 2; // 재선언했으므로 에러 발생
> var i; // 다른 종류로 재선언했으므로 에러 발생
> let i; // 다른 종류로 재선언했으므로 에러 발생
StackOverflow - The strange behavior of let and var in Javascript입니다.