7주차 주제는 엄격 모드(strict mode
)이다.
책에서는 간단한 예제로 코드를 추론하게 하며 시작한다.
function foo() {
x = 10;
}
console.log(x);
위 코드의 결과는 어떻게 될까?
foo
함수 내에서 선언하지 않은 변수 x
에 10
을 할당했다. 이 때, 변수 x
를 찾아야 값을 할당할 수 있기 때문에 자바스크립트 엔진은 변수 x
가 어디에서 선언되었는지 스코프 체인을 통해 검색하기 시작한다.
먼저 foo
함수의 스코프에서 변수 x
를 검색하지만 선언된 변수가 없어서 실패한다. 자바스크립트 엔진은 변수 x
를 검색하기 위해 foo
함수 컨텍스트의 상위 스코프인 전역 스코프에서 변수 x
의 선언을 검색한다.
전역에서도 변수 x
의 선언을 찾을 수 없기 때문에 ReferenceError
를 throw
할 것 같지만 자바스크립트 엔진은 암묵적으로 전역 객체에 프로퍼티 x
를 동적으로 생성한다. 이렇게 x
는 전역 변수가 되고 이렇게 전역 변수가 된 변수를 암묵적 전역 변수(implicit global
)이라고 한다.
개발자와의 의도와는 상관없는 이런 현상들은 오류를 발생시키는 원인이 될 가능성이 크다. 따라서 반드시 var
, let
, const
키워드를 사용하여 변수를 선언해야 한다.
하지만, 오타나 문법 지식의 미비로 인한 실수는 언제나 발생한다. 이런 실수를 근본적으로 해결하기 위해 ES5
부터 strict mode
가 추가되었다.
strict mode
는 자바스크립트 언어의 문법을 보다 엄격히 적용하여 기존에는 무시되던 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.
ESLint
와 같은 린트 도구를 사용하면strict mode
와 유사한 효과를 얻을 수 있다. 린트 도구는 정적 분석 기능을 통해 소스 코드를 실행하기 전에 스캔하여 문법적 오류나 잠재적 오류를 찾아내고 오류의 이유를 알려주는 유용한 도구이다.
strict mode
를 적용하는 것은 어렵지 않다. 적용하고 싶은 스크립트 또는 함수의 최상단에 use strict
; 를 추가하기만 하면 된다.
전역에 추가하면 스크립트 전체에 strict mode
가 적용된다.
"use strict";
function foo() {
x = 10; // ReferernceError: x is not defined
}
foo();
함수의 최상단에 추가하면 해당 함수와 중첩된 내부 함수에 strict mode
가 적용된다.
function foo() {
"use strict";
x = 10; // ReferernceError: x is not defined
}
foo();
전역에 적용한 strict mode
는 스크립트 단위로 적용된다.
<!DOCTYPE html>
<html>
<body>
<script>
"use strict";
</script>
<script>
x = 1; // 에러가 발생하지 않는다.
console.log(x);
</script>
<script>
"use strict";
y = 1; // ReferernceError: y is not defined
console.log(y);
</script>
</body>
</html>
위와 같이 스크립트 단위로 적용되는 strict mode
는 다른 스크립트에 영향을 주지 않는다. 게다가, 이렇게 strict mode
스크립트와 non-strict mode
스크립트가 섞이는 것은 바람직하지 않다. 외부 서드 파티 라이브러리를 사용하고 있고 해당 라이브러리가 non-strict mode
일 경우 추적하기 힘든 오류를 발생시킬 수도 있다.
이러한 경우, 즉시 실행 함수로 스크립트 전체를 감싸서 스코프를 구분하고 즉시 실행 함수의 최상단에 strict mode
를 적용해야 한다.
(function () {
"use strict";
// ...logic
}());
위에 언급한 바와 같이 함수 단위로도 strict mode
를 적용시킬 수 있다. 함수 또한 strict mode
와 non-strict mode
를 혼용하는 것은 바람직하지 않고 일일히 모든 함수에 strict mode
를 적용하는 것은 귀찮은 일이다. 게다가 strict mode
가 적용된 함수가 참조할 외부 함수의 컨텍스트에 strict mode
를 적용하지 않는다면 이 또한 문제가 된다.
(function () {
// non-strict mode
var let = 10; // 에러가 발생하지 않는다.
function foo() {
'use strict';
let = 20; // SyntaxError: Unexpected strict mode reserved word
}
foo();
}());
따라서 strict mode
는 즉시 실행 함수로 감싼 스크립트 단위로 적용하는 것이 바람직하다.
strict mode
의 기능은 다음과 같다.
ReferenceError
가 발생한다.delete
로 삭제하려고 하면 SyntaxError
가 발생한다.SyntaxError
가 발생한다.with
문을 사용하면 SyntaxError
가 발생한다.this
에 undefined
가 바인딩된다.IE.9
이하는 지원하지 않는다.ESLint
를 쓰고 있어서 strict mode
에 대한 필요성을 못 느껴왔다. ESLint
가 strict mode
의 기능들을 포함한 슈퍼셋 느낌이기 떄문이다. 이참에 ESLint
설정을 커스텀해보는 것도 좋을 것 같다.
책에 대한 공부는 개인적으로 해도 되는 부분이지만 이때까지 어느정도의 강제성을 부여하기 위해 스터디를 해왔다. 하지만 스터디에서 결과물이 산출되면 좋을 것 같다는 의견이 모여 블로그 만들기를 시작하려 한다. 책의 진도는 주에 1장으로 줄이고 강제성은 블로그 쓰기로 결정되었고 블로그 만들기는 새로운 기술들에 대한 학습과 적용하며 체화하는 것이 주가 될 것 같다.
블로그 만들기 프로젝트 초기 설정을 할 때 ESLint
에 대해서 좀 더 알아보고 직접 설정을 해봐야겠다.