strict mode (엄격모드)
자바스크립트 언어의 문법을 좀 더 엄격히 적용하여 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시키는 것이다.
'use strict'는 자바스크립트의 의도지 않은 여러 잠재적인 오류를 막아주는데 많은 도움을 주지만, 잘못 사용하면 없던 오류를 새로 만들어내는 애물단지가 될 수 있다.
반대로
공식적인 용어는 아니지만, 가끔 엄격하지 않은 기본값을 sloppy mode (느슨한 모드) 라고 부르기도 한다.
sloppy mode 의 예제 실행결과는 무엇일까?
function foo() {
x = 10;
}
foo();
console.log(x); // 실행결과는 ?
foo 함수 내 선언하지 않은 x 변수에 10을 할당했다.
이때 x 변수를 찾아 x 에 값을 할당할 수 있기 때문에 자바스크립트 엔진은 x 변수가 어디에서 선언되었는지 스코프 체인을 통해 검색하기 시작한다.
foo 함수 스코프 → foo 함수 컨텍스트의 상위 스코프 (예제의 경우 전역 스코프) 순서로 x 변수 선언을 검색한다.
최상위 스코프까지 검색했을 때 x 변수 선언이 존재하지 않기 때문에 ReferenceError를 발생시킬 것 같지만, 엄격모드가 아닌 경우 자바스크립트 엔진은 암묵적으로 전역 객체에 x 프로퍼티를 동적으로 생성한다.
이때 전역 객체의 X 프로퍼티는 마치 전역 변수처럼 사용되는데 이런 현상을 암묵적 전역(implicit global) 이라고 한다.
개발자의 의도와는 상관없이 암묵적 전역은 오류를 발생시키는 원인이 될 가능성이 크다.
따라서 반드시 var, let, const 키워드를 사용하여 변수를 선언 후 사용해야한다.
이런 잠재적 오류를 줄이기 위해 ES5 부터 strict mode (엄격 모드) 가 추가되었다.
strict mode 선언
스크립트의 시작 혹은 함수의 시작 부분에 "use strict" (또는 'use strict') 를 선언하면 strict 모드의 코드를 작성할 수 있다.
스크립트에서 strict 선언
"use strict";
function foo() {
x = 10; // ReferenceError: x is not defined
}
foo();
전역에 적용한 strict mode는 스크립트 단위로 적용된다.
<script>
"use strict";
</script>
<script>
function foo() {
x = 10; // 에러가 발생하지 않음
}
foo();
</script>
함수에서 strict 선언
function foo() {
"use strict";
x = 10; // ReferenceError: x is not defined
}
foo();
코드 선두에 위치시키지 않으면 제대로 동작하지 않는다.
function foo() {
x = 10; // 에러를 발생시키지 않음
"use strict";
}
foo();
use strict 사용으로 발생하는 제약 조건
- 전역 변수를 허용하지 않으며, 전역 변수 선언시 오류 발생
- 변수 이름 선언 및 사용시 "var"가 누락되면 오류 발생
- 값 할당 실패는 오류 발생 (NaN = 1;).
- 삭제할 수없는 속성을 삭제하려고 하면 (Object.prototype 삭제) 오류 발생
- 읽기 전용 속성에 쓰기를 하려고 하면 오류 발생
- 객체 리터럴의 모든 속성 이름은 고유해야한다. (var x = {x1 : "1", x1 : "2"}).
- 함수의 파라메터는 고유해야 한다. (function calc (x, x) {}와 같이 같은 파라미터 이름 중복 사용 금지)
- 8 진수 구문과 8진수 이스케이프 표현 금지(var a = 010; 과 같은 8진수 표현 사용 금지)
- with 키워드 금지
- 'eval', 'agruments'는 예약어로 변수명으로 사용불가능 (var eval = 1;)
- 변수를 생성하는 eval()은 보안상 사용불가능 (eval ("var x = 2");)
- 변수 이름과 함수 이름 삭제 금지 (var a = 1; delete a;)
- arguments.callee 미지원. arguments.callee 속성은 이름이 없는 익명 함수(anonymous function)를 선언해서 사용할 때 실행 중인 함수 안에서 함수 자신을 참조하기 위해 사용. 재귀 호출 방식으로 자신을 호출하는 방식은 잠재적으로 참조 오류를 발생시킬 수 있음
암묵적 전역
선언하지 않은 변수를 참조하면 ReferenceError가 발생한다.
"use strict"
x = 1;
console.log(x); // ReferenceError: x is not defined
변수, 함수, 매개변수의 삭제
delete 연산자로 변수, 함수, 매개변수를 삭제하면 SyntaxError가 발생한다
"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.
매개변수 이름의 중복
중복된 매개변수 이름을 사용하면 SyntaxError가 발생한다.
"use strict";
// SyntaxError: Duplicate parameter name not allowed in this context
function foo(x, x) {
return x + x;
}
console.log(foo(1,2));
with문의 사용
with문을 사용하면 SyntaxError가 발생한다.
"use strict";
// SyntaxError: Strict mode code may not include a with statement
with({
x : 1
}) {
console.log(x);
}
전역 this 바인딩
this 값이 null 또는 undefined인 경우 전역 객체로 변환하지 않는다.
strict mode가 아닌 경우에 전역 this가 window 객체로 자동 바인딩이 된다.
function foo() {
this.print = function() {
console.log(this);
}
}
let f = new foo();
f.print(); // this = foo 객체
let f2 = f.print; // foo의 print method
f2(); // print method 실행 : this = window (전역) 객체
하지만, strict 모드에서는 바인딩해주지 않은 this를 전역객체로 변환해주지 않는다.
"use strict";
function foo() {
this.print = function() {
console.log(this);
}
}
let f = new foo();
f.print(); // this = foo 객체
let f2 = f.print; // foo의 print method
f2(); // print method 실행 : this = undefined (전역 객체로 반환해주지 않는다)
use strict 사용하는지 체크하기
전역 객체인 this와 자바스크립트 함수를 사용해 엄격 모드가 실행 중인지 확인할 수 있다.
전역 this는 엄격모드에서 사용할 수 없기 때문에 this가 사용 가능하면(true 반환) strict 모드이고, 그렇지 않으면(false 반환) strict 모드가 아님을 알 수 있다.
function isStrictMode() {
return !this;
}
'use strict'를 사용한다고 더 안정적인 코드가 되지는 않는다.
'use stict'는 더 엄격하게 코드 사용 규칙을 제한하고, 잠재적으로 오류가 발생할 수 있는 전역 변수 사용을 제한하기 때문에 더 좋은 코드를 작성하는데 도움을 주는 것은 분명하다.
그렇다고 'use strict' 사용이 극적으로 더 안정적인 코드를 만들어주는 것은 아니다.
대부분의 자바스크립트 코드에서 가장 크고 빈번하게 문제를 일으키는 것은 로직의 오류이기 때문에,
'use strict'가 아니어도 이런 잠재적인 대입 문제는 대부분의 경우 이후의 실행 로직에서 문제를 일으켜 오류를 확인하지 못하고 넘어갈 가능성은 생각보다 낮다.
애초에 코딩 스킬이 있어서 이런 기초적인 문제들을 일으키는 코드를 작성하지 않는 개발자라면 'use strict' 사용이 비약적으로 코드의 품질을 높여주거나 오류를 줄여주는 효과가 생기는 것은 아니다.
참고 자료
https://blogpack.tistory.com/972
'Front > JavaScript' 카테고리의 다른 글
[JavaScript] 자바스크립트 날짜 문자열 포맷 반환 함수 만들기 (기본값 매개변수 설정하기) (0) | 2022.04.06 |
---|---|
[Javascript] 자바스크립트의 "특별한 함수" Class의 정의 (0) | 2022.03.18 |
[JavaScript] Custom URL schemes 방식의 VNC 응용프로그램 (서버IP 인자 값 넘기며) 호출 (0) | 2022.01.13 |
[JavaScript] 웹(Chrome)에서 응용 프로그램 실행 시키기 : Registry 이용한 Custom URL schemes 방식 호출 (0) | 2022.01.12 |
[JavaScript] 웹브라우저 동작원리 (Stack, Queue, Event Loop) (0) | 2021.11.01 |
댓글