strict mode
function test() {
x = 5;
}
test();
console.log(x); // ReferenceError 를 발생시킬 것 같지만 전역객체에 x 프로퍼티가 생성되어 5가 출력된다.
위와 같은 현상을 암묵적 전역 이라고 한다. 이러한 암묵적 전역 현상은 오류 발생의 원인이 될 가능성이 높기 때문에 반드시 var, let, const 와 같은 키워드로 변수를 선언하는 것 이 좋다.
하지만 모든 상황에서 이러한 오류 발생의 원인을 반드시 방지하는 것은 어려울 수 있다. 이를 해결하기 위해 ES5 부터 strict mode 가 추가 되었으며 자바스크립트 문법을 좀 더 엄격하게 적용하여 사전에 명시적인 에러를 발생시킨다.
ESLint를 사용해서도 유사한 효과를 얻을 수 있으며 코딩컨벤션 또한 강제할 수 있기 때문에 lint 사용을 권장한다.
strict mode의 적용
전역의 선두 또는 함수 몸체의 선두에 ‘use strict’ 를 추가하여 적용할 수 있다.
그러나 strict mode 적용 시 유의할 점이 있다.
-
전역에 strict mode를 적용하는 것은 스크립트 단위로 적용되기 때문에 strict 와 non-script 가 혼용되어 오류가 발생할 수 있다. (라이브러리가 non-strict 인 경우도 있기 때문)
- 즉시 실행 함수로 스크립트 전체를 감싸서 스코프를 구분하고 그 선두에 strict mode 를 적용하는 것을 추천
- 함수단위로 strict mode를 적용하는 것 또한 각 함수별로 strict mode 적용여부가 달라질 수 있으며 모든 함수에 적용하는 것도 번거로운 일이기 때문에 권장되지 않는다.
따라서 즉시 실행함수로 감싼 스크립트 단위로 적용하는 것이 바람직하다.
strict mode 에러 유형
암묵적 전역
(function () {
'use strict';
x = 5;
console.log(x); // ReferenceError: x is not defined
})();
변수, 함수, 매개변수의 삭제
(function () {
'use strict';
let x = 1;
delete x; // SyntaxError: Delete of an unqualified identifier in strict mode
function test(a) {
delete a; // SyntaxError: Delete of an unqualified identifier in strict mode
}
delete test; // SyntaxError: Delete of an unqualified identifier in strict mode
})();
매개변수 이름의 중복
(function () {
'use strict';
// SyntaxError: Duplicate parameter name no allowed in this context
function test(a, a) {
return a + a;
}
})();
with 문의 사용
with 문은 전달된 객체를 스코프 체인에 추가하는 역할을 한다. 동일한 객체의 프로퍼티를 반복적으로 사용할 때 객체 이름을 생략할 수 있어 코드가 간단해지는 효과가 있지만 성능과 가독성이 나빠지는 문제가 있어 사용하지 않는 것이 좋다.
(function () {
'use strict';
// SyntaxError: Strict mode code may not include a with statement
with ({ a: 1 }) {
console.log(a);
}
})();
strict mode 적용에 의한 변화
일반함수의 this
생성자 함수가 아닌 일반 함수 내부에서는 this를 사용할 필요가 없기 때문에 this에 undefined가 바인딩된다.
(function () {
'use strict';
function test() {
console.log(this); // undefined
}
test();
function Test() {
console.log(this); // Test
}
new Test();
})();
arguments 객체
매개변수에 전달된 인수를 재할당하여 변경해도 arguments 객체에 반영되지 않는다.
(function (a) {
'use strict';
a = 2;
console.log(arguments); // {0: 5, length: 1}
})(5);