[모던 자바스크립트 Deep Dive]20장 strict mode
20.1 strict mode란?
기존의 오류가 발생하기 쉬운 환경
1
2
3
4
5
6
function foo() {
x = 10;
}
foo();
console.log(x); // 10
- 자바스크립트 엔진은
foo
함수의 스코프에서x
변수의 선언을 검색- 없음
- 자바스크립트 엔진은
foo
함수의 상위 스코프, 즉 전역 스코프에서x
변수의 선언을 검색- 없음
- 자바스크립트 엔진은 암묵적으로 전역 객체에
x
프로퍼티를 동적 생성- 전역객체의
x
프로퍼티는 전역 변수처럼 사용 가능해짐
- 전역객체의
이러한 현상을 암묵적 전역이라 하며 이는 높은 확률로 오류를 발생시키는 원인이 된다.
strict mode
- ES5부터 도입
- 잠재적인 오류를 발생시키기 어려운 개발 환경
- 자바스크립트 문법을 엄격히 적용해 오류를 발생시킬 것 같거나, 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 것 같으면 명시적 에러를 발생
- ES6에서 도입된 클래스와 모듈은 기본적으로 strict mode 적용
린트 도구
- 정적 분석 기능을 통해 소스코트를 스캔하여 오류를 찾아내 이를 리포팅해주는 도구
- ESLint같은 린트 도구를 사용하면 strict mode와 유사한 효과를 얻을 수 있지만 린트 도구는 코딩 컨벤션까지 강제할 수 있다.
20.2 strict mode의 적용
전역의 선두 또는 함수 몸체의 선두에
‘use strict’;
를 추가해 적용할 수 있다.1 2 3 4 5 6
'use strict'; function foo() { x = 10; // ReferenceError: x is not defined } foo();
- 함수 몸체의 선두에 추가하면 중첩 함수까지도 strict mode가 적용된다.
코드 선두에 추가하지 않으면 제대로 동작하지 않는다.
1 2 3 4 5
function foo() { x = 10; // 에러를 발생시키지 않는다. 'use strict'; } foo();
20.3 전역에 strict mode를 적용하는 것은 피하자
전역에 적용한 strict mode는 스크립트 단위로 적용된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<!DOCTYPE html> <html> <body> <script> 'use strict'; </script> <script> x = 1; // 에러가 발생하지 않는다. console.log(x); // 1 </script> <script> 'use strict'; y = 1; // ReferenceError: y is not defined console.log(y); </script> </body> </html>
- strict mode 스크립트와 non-strict mode 스크립트를 혼용하는 건 오류 발생 확률을 높인다.
따라서 즉시 실행 함수를 사용해 스코프를 구분하고 함수 선두에 strict mode를 적용하는 것을 권장한다.
1 2 3 4 5 6
// 즉시 실행 함수의 선두에 strict mode 적용 (function () { 'use strict'; // Do something... }());
20.4 함수 단위로 strict mode를 적용하는 것도 피하자
- 어떤 함수에는 strict mode를 적용하고 어떤 함수는 적용하지 않는 것은 번거롭다.
- 모든 함수에 strict mode를 적용하는 것은 번거롭다.
strict mode가 적용된 함수가 strict mode가 적용되지 않은 함수 외부 컨텍스트를 참조하면 문제가 발생할 수 있다.
1 2 3 4 5 6 7 8 9 10 11
(function () { // non-strict mode var lеt = 10; // 에러가 발생하지 않는다. function foo() { 'use strict'; let = 20; // SyntaxError: Unexpected strict mode reserved word } foo(); }());
- 따라서 strict mode는 즉시 실행 함수로 감싼 스크립트 단위로 적용하는 게 바람직하다.
20.5 strict mode가 발생시키는 에러
20.5.1 암묵적 전역
1
2
3
4
5
6
(function () {
'use strict';
x = 1;
console.log(x); // ReferenceError: x is not defined
}());
- 선언하지 않은 변수를 참조하면
ReferenceError
발생
20.5.2 변수, 함수, 매개변수의 삭제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(function () {
'use strict';
var x = 1;
delete x;
// SyntaxError: Delete of an unqualified identifier in strict mode.
function foo(a) {
delete a;
// SyntaxError: Delete of an unqualified identifier in strict mode.
}
delete foo;
// SyntaxError: Delete of an unqualified identifier in strict mode.
}());
delete
연산자로 변수, 함수, 매개변수를 삭제하면SyntaxError
발생
20.5.3 매개변수 이름의 중복
1
2
3
4
5
6
7
8
9
(function () {
'use strict';
//SyntaxError: Duplicate parameter name not allowed in this context
function foo(x, x) {
return x + x;
}
console.log(foo(1, 2));
}());
- 중복된 매개변수 이름을 사용하면
SyntaxError
발생
20.5.4 with
문의 사용
1
2
3
4
5
6
7
8
(function () {
'use strict';
// SyntaxError: Strict mode code may not include a with statement
with({ x: 1 }) {
console.log(x);
}
}());
with
문을 사용하면SyntaxError
발생with
문- 전달된 객체를 스코프 체인에 추가
- 동일한 객체의 프로퍼티를 반복해 사용할 때 객체 이름을 생략할 수 있어 코드를 줄임
- 성능과 가독성이 나빠지므로 사용을 권장하지 않음
20.6 strict mode 적용에 의한 변화
20.6.1 일반 함수의 this
1
2
3
4
5
6
7
8
9
10
11
12
13
(function () {
'use strict';
function foo() {
console.log(this); // undefined
}
foo();
function Foo() {
console.log(this); // Foo
}
new Foo();
}());
- strict mode에서 함수를 일반 함수로 호출하면
this
에undefined
를 바인딩 - 생성자 함수가 아닌 일반 함수 내부에선
this
를 사용할 일이 없기 때문- 사용한다고 해도 에러는 발생하지 않는다.
20.6.2 arguments
객체
1
2
3
4
5
6
7
8
(function (a) {
'use strict';
// 매개변수에 전달된 인수를 재할당하여 변경
a = 2;
// 변경된 인수가 arguments 객체에 반영되지 않는다.
console.log(arguments); // { 0: 1, length: 1 }
}(1));
- strict mode에서 매개변수에 전달된 인수를 재할당해 변경해도
arguments
객체에 반영되지 않음
This post is licensed under CC BY 4.0 by the author.