자바스크립트 strict mode

해잉·2022년 6월 20일
0
post-custom-banner

자바스크립트로 코딩테스트를 보다가 맨 첫줄에 strict mode라는 것을 발견했다. 무엇일까?

Strict mode

strict mode : 엄격 모드 라고 MDN은 번역하고있다. 엄격하지 않은 기본값을 sloppy mode: 느슨한 모드 라고 하는데, strict mode는 sloppy mode에 비해 세 가지 차이가 있다.

  1. 기존에는 조용히 무시되던 에러들을 throwing 한다.
  2. JavaScript 엔진의 최적화 작업을 어렵게 만드는 실수들을 바로잡는다. (가끔씩 strict mode의 코드는 sloppy mode의 동일한 코드보다 더 빨리 작동하도록 만들어진다.)
  3. strict mode는 ECMAScript의 차기 버전들에서 정의될 문법을 금지합니다.

Strict mode 적용하기

Strict mode는 전체 스크립트 또는 부분 함수에 적용할 수 있다. 하지만 {} 괄호로 묶여진 블럭문에는 적용되지 않는다. 컨텍스트와 같은 곳에 적용을 시도하면 동작하지 않는다. eval코드 Function코드, 이벤트 핸들러 속성, WindowTimers.setTimeout()과 연관된 함수들에 전달된 문자열이 전체 스크립트이며 여기에서 Strict mode가 예상대로 동작한다.

전체 스크립트에 strict mode 적용

strict mode를 전체 스크립트에 적용하기 위해서 정확한 구문 "use strict"; 또는 'use strict';을 다른 구문 작성 전에 삽입한다.

스크립트 끼리의 결합은 이상적이지 않다는 것을 차치하고나더라도, strict mode 와 sloppy mode의 결합은 문제를 일으킬 수 있다. strict mode + strict mode, sloppy mode + sloppy mode의 결합은 괜찮다.

함수에 strict mode 적용

함수 본문 처음에 "use strict"; 또는 'use strict';을 삽입한다.

function strict() {
	// 함수 레벨 strict mode
    'use strict';
    function nested() { return "And so am I" }
    return "Hi! I'm a strict mode function!" + nested();
}
function notStrict() {
	return "I'm not strict.";
}

모듈에 strict mode 적용

ECMAScript 2015는 JavaScript 모듈을 소개했다. JavaScript 모듈의 전체 콘텐츠는 strict mode 시작을 위한 구문 없이도 자동으로 strict mode이다.

JavaScript 모듈 : export
export문은 JavaScript 모듈에서 함수, 객체, 원시 값을 내보낼 때 사용한다. 내보낸 값은 다른 프로그램에서 import문으로 사용할 수 있다.

Strict mode에서의 변화

strict mode는 syntax와 런타임 동작을 모두 변경한다. JavaScript의 sloppy mode에서는 허용되었던 실수를 에러가 발생하게끔 변경하고, 변수 사용을 단순화할 수 있도록 하고, evalarguments를 더 간단하게 만든다.

1. 실수를 에러로 발생시키기

sloppy mode에서는 허용되었던 실수를 에러가 발생하게끔 변경한다.

(1) 실수로 전역 변수를 생성하는 것을 불가능하게 한다.
일반적인 JavaScript에서 변수를 잘못 입력하면 전역 객체에 대한 새 속성이 만들어지고 그대로 동작하지만, 전역 변수를 생성하는 할당은 strict mode에서는 에러를 발생시킨다.

"use strict";
let mistypeVariable;
                      
mistypeVarible = 17; // 전역 변수 mistypeVarible("a" 오타)이 존재하지 않는다고 가정하고 Referrence Error를 발생시킨다.

(2) 할당에서 발생한 문제를 조용히 넘어가지 않고 에러를 발생시킨다.
보통의 JavaScript에서 조용히 넘어가는 쓸 수 없는 global 혹은 property에의 할당, getter-only property에의 할당, 확장 불가 객체에 대한 새 property 할당에서 에러를 발생시킨다.

'use strict';

// 쓸 수 없는 global에 할당
var undefined = 5;  // TypeError 발생
var Infinity = 5; // TypeError 발생

// 쓸 수 없는 property에 할당
var obj1 = {};
Object.defineProperty(obj1, 'x', { value: 42, writable: false });
obj1.x = 9; // TypeError 발생

// getter-only property에 할당
var obj2 = { get x() { return 17; } };
obj2.x = 5;  // TypeError

// 확장 불가 객체에 새 property 할당
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // TypeError 발생

getter-only 프로퍼티란? 할당(set)할 수 없는, 획득(get)만 가능한 property
참고 : 프로퍼티 getter와 setter

(3) 삭제할 수 없는 property를 삭제하려고 할 때 에러를 발생시킨다.

"use strict";
delete Object.prototype; // TypeError 발생

(4) Gecko 34 이전의 모드에서는(ES 2015에서 오류를 발생하지 않는 것으로 원복됨) 오브젝트의 모든 프로퍼티의 이름이 고유해야 했다.

(5) 함수의 파라미터 이름이 고유해야 한다.
보통의 코드에서는 파라미터명이 중복될 경우 마지막 파라미터의 존재가 동일한 이름을 가진 이전 파라미터를 감추게 된다. 따라서 파라미터 명이 중복될 경우 문법 오류가 발생한다.

function sum (a, a, c) {  // Syntax Error
	'use strict';
    return a + b + c;  
}

(6) ES5의 strict mode에서는 8진수 표현법을 금지한다. 8진수 표현법은 ES5의 일부는 아니지만 모든 브라우저에서 앞에 0을 붙임으로써 표현이 가능하다. 0644 === 420 ES2015에서는 접두사 0o를 붙여 8진수를 지원한다.

var a = 0o10;  // ES2015: Octal

하지만, 앞자리에 0을 붙여 8진수로 만드는 것은 실수를 유발할 가능성이 높기 때문에 에러를 발생시킨다.

'use strict';
var sum = 015 +  // Syntax Error
		  197 +
          142;

var sumWithOctal = 0o10 + 8;
console.log(sumWithOctal); // 16

(7) ES5의 strict mode에서는 원시 타입의 변수에 프로퍼티를 추가하는 것을 허용하지 않는다. sloppy mode에서는 이러한 코드는 단순히 무시되지만 strict mode에서는 TypeError를 발생시킨다.

(function() {
"use strict";

false.true = "";  // TypeError
(14).sailing = "home";  // TypeError
"with".you = "far away"; // TypeError

})();

2. 변수 사용을 단순화

(1) with을 사용하지 못하게 한다.

"use strict";
var x = 17;
with (obj) // Syntax Error

3. evalarguments를 간단하게 하기

아직 궁금한 점
1. 가끔식 strict mode의 코드는 sloppy mode의 코드보다 더 빨리 작동하도록 만들어진다. 라고 서술되어있는데 이건 무슨 원리일까? 🤔

참고
MDN web docs Strict mode

post-custom-banner

0개의 댓글