Programming/JavaScript & TypeScript

Strict mode(엄격 모드), use strict 란?

Bonita SY 2020. 9. 29. 20:12
728x90
반응형

Strict mode (엄격모드)

- ECMAScript 5에서 소개됨

- JavaScript의 제한된 버전을 선택하여 암묵적인 느슨한 모드(Sloppy mode)를 해제하기 위한 방법

 

특징

- 엄격모드를 지원하지 않는 브라우저(Internet Explorer 10 버전 이하)에서는 엄격 모드의 코드가 다른 방식으로 동작 (그렇기 때문에 엄격 모드에 의존하면 안됨)

- 엄격모드의 code와 비엄격모드의 code는 공존 가능 => 엄격 모드를 일부만 선택하는 것이 점진적으로 가능하게 됨

- 전체 스크립트 또는 부분 함수에 적용 가능

- {} 괄호로 묶여진 block 문, context에 적용되지 않음

 

엄격모드 사용 시 JavaScript symantic의 변화

1. 기존에 조용히 무시되던 에러들이 throwing

1) 변환 실수를 오류로 해석 (문법 에러, 런타임에러 등)

 

(1) 글로벌 변수명 틀림

"use strict";
                       // 전역 변수 mistypedVariable 이 존재한다고 가정
mistypedVaraible = 17; // 변수의 오타때문에 이 라인에서 ReferenceError 를 발생시킴

(2) 사용할 수 없는 변수에 값 할당

"use strict";

// 쓸 수 없는 프로퍼티에 할당
var undefined = 5; // TypeError 발생
var Infinity = 5; // TypeError 발생

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

// getter-only 프로퍼티에 할당
var obj2 = { get x() { return 17; } };
obj2.x = 5; // TypeError 발생

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

(3) 삭제할 수 없는 property 삭제 시

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

(4) 객체 리터럴의 모든 프로퍼티의 이름이 유니크하지 않을 때

"use strict";
var o = { p: 1, p: 2 }; // !!! 구문 에러

ECMAScript 2015부터는 에러가 아님

 

(5) 유니크한 함수 파라미터를 사용하지 않을 때

function sum(a, a, c){ // !!! 구문 에러
  "use strict";
  return a + b + c; // 코드가 실행되면 잘못된 것임
}

(6) 8진 구문 사용

var a = 0o10; // ES6: 8진수

- ECMAScript5에서 엄격모드는 8진 구문을 금지

- 8진 구문은 ES5의 문법이 아니지만, 모든 브라우저에서 앞에 0을 붙혀야 지원

- ECMAScript2015에서 접두사 "0o"를 붙혀 8진수를 지원

 

(7) ECMAScript 6 의 엄격모드는 primitive 값에 프로퍼티를 설정하는 것을 금지

(function() {
"use strict";

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

})();

- 비엄격모드에서는 무시됨 (no-op)

 

2. JavaScript 엔진의 최적화 작업을 어렵게 만드는 실수를 바로 잡음

=> 엄격 모드의 코드는 비엄격모드의 동일한 코드보다 더 빨리 작동할 수 있음

 

1) 변수 사용 단순화

(1) with 사용 불가

"use strict";
var x = 17;
with (obj) // !!! 구문 에러
{
  // 엄격모드가 아니라면, 이는 var x 가 되어야 하나요,
  // obj.x 가 되어야 하나요? 
  // 일반적으로는 코드를 실행하지 않고 이를 말하는 것은 불가하므로,
  // 이름을 최적화 할 수 없습니다.
  x;
}

- with는 런타임 중에 블록 안의 모든 이름이 전달된 객체의 프로퍼티나 다른 스코프 내의 변수로 매핑될 수 있음

- 엄격 모드는 with 를 구문 에러로 만들어, with 의 이름이 런타임에 알 수 없는 위치를 참조하지 않도록 함

 

(2) 엄격모드의 eval은 새로운 변수를 주의 scope에 추가하지 않음

function strict1(str){
  "use strict";
  return eval(str); // str 은 엄격모드 코드로 다뤄짐
}
function strict2(f, str){
  "use strict";
  return f(str); // eval(...) 이 아님:
                 // str 은 엄격모드를 적용한 경우에만 엄격함
}
function nonstrict(str){
  return eval(str); // str 은 엄격모드를 적용한 경우에만 엄격함
}

strict1("'엄격모드 코드!'");
strict1("'use strict'; '엄격모드 코드!'");
strict2(eval, "'느슨한 코드.'");
strict2(eval, "'use strict'; '엄격모드 코드!'");
nonstrict("'느슨한 코드.'");
nonstrict("'use strict'; '엄격모드 코드!'");

- 엄격모드 eval 코드 내의 이름은 엄격모드 코드 내의 이름이 eval 의 결과로 evaluated 되지 않은 것과 동일하게 동작

 

(3) delete 구문 금지

"use strict";

var x;
delete x; // !!! 구문 에러

eval("var y; delete y;"); // !!! syntax error

 

2) eval, arguments 단순화

(1) eval과 arguments는 bounding되거나 할당될 수 없음

"use strict";
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 17;"); // 모두 에러

(2) arguments 객체가 생성한 property를 alias하지 않음

function f(a){
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);

(3) arguments.callee 지원하지 않음

"use strict";
var f = function() { return arguments.callee; };
f(); // TypeError

 

3) 안전한 자바스크립트를 작성하도록 도움

(1) window 객체를  this 를 통해 참조할 수 없음

"use strict";
function fun() { return this; }
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);

(2) ECMAScript의 일반적인 확장 사용 불가

function restricted()
{
  "use strict";
  restricted.caller;    // throws a TypeError
  restricted.arguments; // throws a TypeError
}
function privilegedInvoker()
{
  return restricted();
}
privilegedInvoker();

 

3. ECMAScript의 차기 버전들에서 정의될 문법 사용을 금지

1) 미래 ECMAScript의 진화에 대비

(1) 예약어와 동일한 이름, 변수, argument로 사용 불가

- 엄격 모드에서의 식별자 후보들은 예약어 (implementsinterfaceletpackageprivateprotectedpublicstaticyield)임

- 엄격 모드에서 이 예약어와 똑같은 이름을 사용하거나, 변수명 또는 아규먼트명으로도 사용할 수 없음

function package(protected){ // !!!
  "use strict";
  var implements; // !!!

  interface: // !!!
  while (true){
    break interface; // !!!
  }

  function private() { } // !!!
}
function fun(static) { 'use strict'; } // !!!

(2) 스크립트나 함수의 top level이 아닌 곳에서의 함수 내용 정의를 제한

"use strict";
if (true){
  function f() { } // !!! syntax error
  f();
}

for (var i = 0; i < 5; i++){
  function f2() { } // !!! syntax error
  f2();
}

function baz(){ // kosher
  function eit() { } // also kosher
}

 

※ Sloppy mode (비엄격모드, 느슨한 모드)

- 공식 용어는 아님

- 기본값

 

엄격모드 적용 방법

1. 전체 스크립트에 엄격 모드 적용

예제)

'use strict';
...
var v = "Hi!  I'm a strict mode script!";

- 전체 스크립트에 적용하기 위해 "use strict"; 추가

- 아주 주의하면서 사용해야함

 

2. 함수에 엄격모드 적용

예제)

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."; }

- 함수 본문 처음에 "use strict"; 추가

- 전체 스크립트에 엄격 모드를 추가하는 것보다 해당 방법을 권장함

 

3. 모듈에 엄격모드 적용

function strict() {
    // 모듈이기때문에 기본적으로 엄격합니다
}
export default strict;

- 위와 같이 사용하면, JavaScript 모듈의 전체 컨텐츠는 자동으로 엄격모드

 

 

 

 

 

 

출처

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Strict_mode

 

 

 

728x90
반응형