본문 바로가기
Study-Note/JavaScript

18. 자바스크립트의 Strict mode

by Ji-u 2022. 2. 4.

안녕하세요. 좋아요요정입니다.

오늘은 자바스크립트의 strict mode에 대해 알아보겠습니다.

 

 

 

 Strict mode

자바스크립트는 구현되는 환경에 따라 this가 객체인스턴스, 윈도우, 생성되는 객체, 호출되는 객체 등으로 변경이 되고, var, const let 키워드에 따라 다르게 적용되는 스코프, 그리고 함수 호이스팅, 전역변수의 호이스팅,  심지어 var는 같은 변수명이어도 에러가 나지 않는 모습을 보입니다. 자바스크립트의 이런 특징으로 인해 어디서 오류가 발생했는지 파악까지 오랜 시간이 걸리는 경우도 있습니다.

자바스크립트는 잠재적인 오류가 발생하기 어려운 환경을 제공해주기 위해 자체적으로 strict mode를 제공합니다.

 

strict mode
1. strict mode를 적용하면 기존에 조용히 무시되던 에러들이 발생합니다. 
2. 자바스크립트 엔진의 최적화 작업을 어렵게 만드는 실수들을 바로잡습니다.
3. ECMAscript 차기 버전들에서 정의 될 문법을 금지합니다.

 


 

strict mode 적용하기

"use strict"; 혹은 'use strict';

strict mode는 전체 스크립트 또는 부분 함수의 선두(다른 구문 작성 전)에 "use strict"; 이라는 정확한 구문을 추가해주면 적용 가능합니다. use strict가 추가되면 스크립트 전체에 strict mode가 적용됩니다. 자바스크립트 모듈에서는 엄격 모드 시작을 위한 구문없이도 자동으로 strict mode가 됩니다.

 

 

 

 

 

strict mode를 적용 예시

'use strict';

funcion inner() {
	x = "키워드가 없이 선언하면 전역변수로 선언되었었음. strict mode라면?";
}

inner();

console.log(x);

변수 선언문이 없이 변수를 선언하는 경우 자바스크립트 엔진은 암묵적으로 전역 객체의 프로퍼티에 등록하게 됩니다. 

strict mode가 아닌 경우 x를 출력하면 정상적으로 출력됩니다.  strict mode를 사용하게되면 RefernceError를 출력합니다. 

 

 

 

 

전역에 strict mode를 적용한다고 모든 스크립트에 적용되지 않는다.

strict mode를 전역에 적용하게 되면 모든 스크립트들에 적용되는 것이 아니라, strict mode를 선언한 스크립트에서만 적용됩니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
</head>
<body>
  <script>
    'use strict';
  </script>
  <script>
    x = 1; // 에러가 발생하지 않습니다!
    console.log(x) // 1
  </script>
  <script>
    'use strict';
    y = 1; // Reference Error!
  </script>
</body>
</html>

strict mode의 경우 변수 선언문 없이 변수를 선언하는 경우 에러가 발생합니다. 

strict mode가 아닌 경우 전역 객체의 프로퍼티로 등록됩니다.

현재 예제를 보시면 <script></script> 태그가 3개가 있고, 최 상단에 적용을 했다고 모든 script가 엄격모드가 되는 것이 아님을 확인할 수 있습니다.

 

 

 

 

strict mode 와 sloppy mode의 공존을 피하자

sloppy mode는 엄격하지 않은 기본값으로 느슨한 모드라고 부르기도 합니다. (MDN) 

strict mode는 부분 함수의 선두에도 적용이 가능합니다. 그러나 함수 단위로 strict mode를 적용하면, 하나의 스크립트 안에 엄격 모드와 비엄격 모드의 공존으로 의도치 않은 에러가 발생할 수 있습니다.

function strict() {
  'use strict';
  x = 10; // Reference Error
}

function sloppy() {
  y = 10
}


console.log(y) // 10

또한 함수 단위로 다 use strict를 사용하는건 너무나 번거로운 일이기 때문에 추천하지 않는 방법입니다.

 

 


 

strict mode가 발생시키는 에러

strict mode를 적용하면 기존에 조용히 무시되던 에러들이 발생합니다. 개발자가 주로 발생시키는 에러 중 strict mode가 억제시켜줄 수 있는 대표적인 사항 몇가지를 살펴보겠습니다.

 

1. 암묵적 전역

'use strict'; 

function strict() {
  x = 1; 
}

console.log(x) // reference error!

strict mode는 실수로 글로벌 변수를 생성하는 것을 불가능하게 만듭니다. 자바스크립트 엔진은 변수 선언문없이 생성되는 경우 전역 객체의 프로퍼티로 저장하고 오류 없이 동작했지만, strict mode는 rererence error를 출력합니다.  전역 객체에 프로퍼티 등록이 필요한 경우 직접 할당해주는 방법으로 진행할 수 있습니다.

 

 

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 

var obj2 = { get x() { return 17; } }; //getter만 있는 객체에 할당 금지
obj2.x = 5; // TypeError 

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

기존 자바스크립트의 경우 쓸수 없는 전역 변수, 프로퍼티에 값을 할당할 경우 아무런 에러 없이 진행됩니다.

strict mode의 경우 쓸수 없는 프로퍼티에 할당하거나, getter만 존재하는 프로퍼티에 값을 할당한다거나, 확장 불가한 객체에 새 프로퍼티를 할당할 때 에러를 발생시킵니다.

또한 삭제할 수 없는 프로퍼티를 삭제하려고 할 때 에러를 발생시킵니다. 예를들어 오브젝트의 prototype을 삭제하는 경우 말이죠.

 

 

 

3. 매개변수 이름의 중복 금지

"use strict";

function add(num, num) {
  return num + num;
}

console.log(add(10, 201)); // 201 + 201 반환

strict mode에서 중복되는 인수명은 구문 에러를 발생시킵니다. 

기존 느슨한 모드에서는 마지막에 들어오는 인수값이 num에 할당되어 201 + 201의 값이 에러없이 반환되게 됩니다. 이는 개발자가 원하던 의도가 아니었겠죠..

 

 

 

4. primitive값에 프로퍼티를 설정하는 것을 금지

"use strict";

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

strict mode가 아닌 경우 프로퍼티 설정이 무시되지만, 엄격 모드에서는 에러를 발생시킵니다.

 

 

 


strict mode 적용에 의한 변화

strict mode를 사용할 때 주의해야할 점이 있습니다.

 

1. 일반 함수의 this

"use strict";

function thisTest() {
  console.log(this); // undefined
}

function ConstructorFunction() {
  console.log(this); // ConstructorFunction {}
}

new ConstructorFunction();

strict mode에서 함수를 일반 함수로 호출하면, this가 undefined로 바인딩이 됩니다. 이는 생성자 함수가 아니라면, 굳이 함수 내부에서는 this를 사용할 필요가 없기 때문입니다.

 

 

2. arguments 객체

"use strict";

function double(num) {
  num = 10;
  console.log(arguments);
  return num * 2;
}

double(2); // { 0: 2 }

또한, strict mode에서는 매개변수에 전달된 인수들을 재할당해서 변경해도 arguments 객체에 반영되지 않습니다.

 

 

 


오랜만에 블로그 게시글을 작성했네요..

즐거운 설 명절연휴되셨나요? 

저는 이번 명절이 무려 5일이나 되길래 꽉꽉 채워서 공부, 포트폴리오, 블로그 작성, 서브프로젝트 계획을 세워놨었답니다.

그런데 제가 계속 공부만하며 바쁘다고 만남을 미루고, 코로나 핑계로 집에서 공부해왔더니 가족들이 서운함을 가지고 있더라구요..

아차 싶었어요. 내가 너무 내 생각만 했구나. 

내 앞날에 대한 걱정에 주변을 돌보지 못하고 있던걸 깨달았어요. 눈 앞에 일에 급급하며 소중한 것을 너무 미뤄두며 살고 있더라구요.

그래서 이번 명절은 1.5일만 공부하고 남은 3.5일은 가족과 함께 했습니다. 제 좁은 시야를 사과드리고, 위로도 받고, 가족들 웃는 얼굴들도 실컷 보고, 맛있는 것도 함께 먹고, 윷놀이로 돈도 따고..ㅎㅎ 

주변을 돌아보는 여유가 있는 사람이 될 수 있도록 노력해야겠습니다.. 아직 너무 어렵네요.

어렵다고 포기하지 않고(!), 주 1~2회 부모님께 전화할 수 있도록 해봐야겠습니다. 

행복한 코딩라이프, 그리고 행복한 가정되세요~~! 

 

JavaScript 스터디 팀 러버덕과 함께 합니다.