자바스크립트 ES5에서는 새로운 기능이 추가되고 기존 기능 중 일부가 변경되었습니다. 기존 기능을 변경하였기 때문에 하위 호환성 문제가 발생하게 되는데 이러한 문제를 대비해서 변경사항 대부분은 ES5의 기본 모드에선 활성화되지 않도록 적용하였습니다.
대신 use strict라는 특별한 지시자를 사용해 엄격 모드(strict mode)를 활성화했을 때만 이 변경사항이 활성화되게 해 놓았습니다.
💡 strict 모드란?
ECMAScript 5에서 처음으로 소개된 strict 모드는 자바스크립트 코드에 더욱 엄격한 오류 검사를 적용해 줍니다. 엄격 모드는 전체 스크립트 또는 부분 함수에 적용 가능합니다. 함수에 적용할 경우에는 "use strict"는 스크립트 최상단이 아닌 함수 본문 맨 앞에 사용하면 됩니다. 이렇게 하면 오직 해당 함수만 엄격 모드로 실행됩니다. 단, {} 괄호로 묶인 블록 문에는 적용되지 않습니다.
✔ 스크립트 전체에서 strict 적용
// 전체 스크립트 엄격 모드 구문
"use strict";
// 이 코드는 모던한 방식으로 실행됩니다.
const v = "Hi! I'm a strict mode script!";
✔ 함수에서 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 모드를 사용하는 이유?
엄격 모드는 평범한 JavaScript 시멘틱스에 몇 가지 변경이 일어나게 합니다.
- 기존에는 조용히 무시되던 에러들을 throwing합니다.
- JavaScript 엔진의 최적화 작업을 어렵게 만드는 실수들을 바로잡습니다. 가끔씩 엄격 모드의 코드는 비-엄격 모드의 동일한 코드보다 더 빨리 작동하도록 만들어집니다.
- 엄격 모드는 ECMAScript의 차기 버전들에서 정의 될 문법을 금지합니다.
✔ strict 모드를 지원하는 주요 웹 브라우저의 버전
💡 strict 모드의 특징
엄격 모드에서는 이전에 통용되던 행동들을 제약합니다. 또한, 몇 가지 중요한 기능을 수정하여 강력한 오류 검사와 함께 향상된 보안 기능을 제공합니다.
✔ 실수를 에러로 변환(Converting mistakes into errors)
자바스크립트는 오류를 어느 정도 무시하고 넘어갈 수 있습니다. 이것이 편하게 코딩을 할 수 있게 하지만, 때로는 심각한 버그를 만들게 됩니다. strict 모드는 이러한 실수를 에러로 변환하여 즉시 수정할 수 있게 합니다.
👉 선언하지 않고 전역 변수를 만들 수 없습니다.
"use strict"
testvar = 4;
👉 writable이 false로, 읽기 전용 객체에 쓰는 것이 불가능합니다. (read only 객체 수정 불가능)
※ writable이 true일 때만 수정이 가능합니다.
"use strict";
var testObj = Object.defineProperties({}, {
prop1: {
value: 10,
writable: false // by default
},
prop2: {
get: function () {
}
}
});
testObj.prop1 = 20;
testObj.prop2 = 30;
👉 get으로 선언된 객체는 수정할 수 없습니다. (getter-only property 수정 불가능)
"use strict";
var obj2 = { get x() { return 17; } };
obj2.x = 5; // throws a TypeError
👉 extensible 특성이 false로 설정된 객체에 속성을 확장할 수 없습니다. (확장 불가 객체 확장 불가능)
"use strict";
var testObj = new Object();
Object.preventExtensions(testObj);
testObj.name = "Bob";
👉 delete를 호출할 수 없습니다.
"use strict";
var testvar = 15;
function testFunc() {};
delete testvar;
delete testFunc;
Object.defineProperty(testObj, "testvar", {
value: 10,
configurable: false
});
delete testObj.testvar;
변수, 함수 또는 인수 삭제
👉 리터럴 객체는 동일한 이름의 property를 가질 수 없습니다. (하지만 ES6는 가능함)
"use strict";
var o = { p: 1, p: 2 }; // !!! syntax error
👉 함수의 동일한 매개 변수 이름을 선언하는 것이 불가능합니다.
"use strict";
function testFunc(param1, param1) {
return 1;
};
👉 8진수 숫자 리터럴 및 이스케이프 문자를 사용할 수 없습니다.
"use strict";
var testoctal = 010;
var testescape = \010;
8진수 사용, 8진수 값에 이스케이프 사용
👉 primitive values의 속성 설정이 불가능합니다.
strict 모드가 아닌 경우, 에러가 발생하지 않지만, 해당 코드는 무시됩니다.
(function() {
"use strict";
false.true = ""; // TypeError
(14).sailing = "home"; // TypeError
"with".you = "far away"; // TypeError
})();
👉 변수 사용의 명료화(Simplify variable uses)
strict 모드는 변수 이름의 맵핑을 단순화합니다. 대부분의 컴파일러의 최적화는 변수의 매핑에 달려 있습니다. 자바스크립트 또한 변수의 매핑이 최적화의 크리티컬 이슈입니다. strict 모드를 사용하여 자바스크립트를 최적화할 수 있습니다.
👉 with를 사용할 수 없습니다.
var foo = {
name: "foo"
}
with (foo) {
console.log(name);
}
with를 위와 같이 사용할 수 있습니다. 하지만 with 블록 안에 name은 전역 변수의 name인지 foo의 name인지 모호합니다. 그렇기 때문에 strict 모드에서는 with를 사용하는 것이 불가능합니다.
"use strict";
var x = 17;
with (obj) // !!! syntax error
{
// If this weren't strict mode, would this be var x, or
// would it instead be obj.x? It's impossible in general
// to say without running the code, so the name can't be
// optimized.
x;
}
👉 eval 함수는 주변 스코프에 새로운 변수를 추가하지 않습니다.
var x = 17;
var evalX = eval("'use strict'; var x = 42; x");
console.log(x);
console.log(evalX);
👉 eval과 arguments 명료화(Making eval and arguments simpler)
strict 모드는 eval과 arguments 사용을 더욱 명료하게 사용할 수 있게 합니다.
👉 eval을 변수 또는 함수, 매개 변수의 이름으로 사용할 수 없습니다.
"use strict";
eval = 17;
++eval;
var eval;
function x(eval) { }
var y = function eval() { };
👉 arguments를 변수 또는 함수, 매개 변수의 이름으로 사용할 수 없습니다.
"use strict";
arguments++;
var obj = { set p(arguments) { } };
try { } catch (arguments) { }
function arguments() { }
var f = new Function("arguments", "'use strict'; return 17;");
👉 인자 값을 수정함으로 arguments의 값이 수정되지 않습니다.
function f(a){
"use strict";
a = 42;
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0]);
console.log(pair[1]);
👉 callee를 지원하지 않습니다.
"use strict";
var f = function() { return arguments.callee; };
f(); // throws a TypeErrorr
👉 this의 값이 null 또는 undefined인 경우 전역 객체로 변환하지 않습니다.
this의 결과가 undefined의 경우 window 객체로 변환하지 않고, undefined가 그대로 보이게 됩니다.
"use strict";
function fun() { return this; }
console.log(fun());
console.log(fun.call(2));
console.log(fun.apply(null));
console.log(fun.call(undefined));
console.log(fun.bind(true)());
👉 callee, caller를 통해 stack 검색이 불가능합니다.
function restricted() {
"use strict";
restricted.caller; // throws a TypeError
restricted.arguments; // throws a TypeError
}
function privilegedInvoker() {
return restricted();
}
privilegedInvoker();
👉 arguments의 caller를 지원하지 않습니다.
"use strict";
function fun(a, b)
{
"use strict";
var v = 12;
return arguments.caller; // throws a TypeError
}
fun(1, 2); // doesn't expose v (or a or b)
현재 ECMA Script는 arguments.caller를 제공하지 않습니다. 하지만 이전의 버전에서는 arguments.caller를 제공되어 왔습니다. strict 모드 사용 시 이전의 ECMA Script에서도 arguments.caller 사용이 불가능합니다.
👉 예약된 키워드의 이름으로 변수 또한 함수를 생성할 수 없습니다.
"use strict"
var implements = "";
var interface = "";
var package = "";
var private = "";
var protected = "";
var public = "";
var static = "";
var yield = "";
👍 기존 자바스크립트의 문법과 다른 strict 모드의 문법을 표로 정리한 내용입니다.
정리: 스크립트를 사용하는 사람마다 조금씩 차이가 있겠지만(저는 eval, with는 사용해본 적이 없습니다.)
주관적인 관점으로 제가 느낀 strict 모드를 사용할 때 이점은
- 선언되지 않은 Global변수를 사용할 수 없음
- 읽기 전용 프로퍼티에는 대입할 수 없음
- 매개변수 이름이 중복되어서는 안 됨.
- this 포인터가 가리키는 값이 null, undefined인 경우 전역 객체로 반환되지 않음
- 예약어를 사용할 수 없음
위의 5가지 인 것 같습니다.
어디까지나 저의 주관적인 관점이고 저도 좀 더 자바스크립에 대한 지식이 커지면 해당 의견은 언제든 바뀔 수 있을 거 같아요.
감사합니다.
참고:
'IT > JavsScript' 카테고리의 다른 글
GSAP 트윈맥스(Tween Max) 재대로 톺아보기 (0) | 2022.12.01 |
---|---|
함수형 프로그래밍 이해하기 (1) | 2022.08.24 |
프로토타입(Prototype) 이해하기 (1) | 2022.07.14 |
비동기 처리 방식 알아보기 (Promise, Callback, Async, Await) (0) | 2022.07.14 |
이벤트 루프와 태스크 큐 (마이크로 태스크, 매크로 태스크) (1) | 2022.07.13 |
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)