티스토리 뷰

Java Script & HTML

Strict Mode

LichKing 2017. 4. 30. 17:20

1. arguments 객체

자바스크립트는 매우 유연한 언어이다. 얼마나 유연하냐면 언어차원에서 제공하는 객체들의 속성까지 변경할 수 있다. 이 코드를 보자.


var test = function(arg){
arguments = [];
};

test("hello");


결과는 직접 확인해보자. 브라우저 개발자도구 열고 복붙하면 확인할 수 있다.

arguments는 함수의 인자들을 관리하는 자바스크립트 엔진이 제공하는 기본적인 객체다. 일반적으로 개발할때 저걸 수정할일은 없지만(그럴일이 있다하더라도 arguments객체를 수정하는건 권장하지않는다.) 수정이 된다.


2. 생성자와 함수

또한 자바스크립트는 생성자와 함수의 역할도 함수가 혼자 다한다.

var Cons = function(name, age){
this.name = name;
this.age = age;
};

var obj = new Cons("Lichking");


자바스크립트에 익숙하지않아도 자바에 익숙한 분들이라면 대충 어떻게 돌아갈지 예상이 될거라 본다. 하지만 위에서도 말했듯 함수는 지혼자 생성자도하고 함수역할도 한다면 이런 문법도 가능하다.


var Cons = function(name, age){
this.name = name;
this.age = age;
};

var obj = Cons("Lichking");


뭐가 달라진건지 모르겠다면... 아래쪽 코드에서 new가 제외됐다. 인터프리터 언어로 컴파일 타임이 없는 자바스크립트에선 사전에 에러를 잡아낼수없다. 또한 저 코드는 실질적으로 문법 오류가 없는 문법으로 런타임에도 에러는 발생하지않는다. 그럼 new가 없으면 어떻게 작동할까?


이번 포스팅의 주제가 이건 아니긴하지만.. 자바스크립트의 this는 런타임시에 바인딩이 결정되게 되는데 new가 존재하지않을시에 함수 실행 주체는 전역객체가 되게된다. 일반 브라우저에서 전역객체는 window가 되어 해당 함수는 전역에 name과 age 변수를 추가하고 초기화하게된다. 만약 이전에 전역에 name과 age가 존재했다면 해당 변수는 내용이 바뀌게 되는것이다.


이걸 방지하기위해선 함수를 호출하기 이전엔 항상 이 함수의 역할이 무엇인지를 확인하고 적절히 써야할것이다. 하지만 사람이란 언제나 실수를 할수있다는것을 생각한다면 언어차원에서 생성자와 함수를 구분하지않는것이 매우 아쉬운 부분이다.


3. var 없는 변수

자바스크립트는 동적 언어이기때문에 변수를 선언할 때 타입을 지정하는것이 아니다. 단지 변수라는걸 알리기위해 var 라는 예약어를 사용한다.

하지만 문제는 var가 없어도 변수 선언이 된다는 점이다.


var func = function(name){
gName = name;
};

func("LichKing");
console.log(gName);


func() 함수 내에 gName 변수는 var가 없다. 이런경우 gName은 묵시적으로 전역변수로 선언된다. 때문에 해당 코드는 에러가 나는것이 아니라 LichKing이 출력되게 된다. 이 기법을 유용하다고 생각할 분이 계실지도 모르겠지만 이런 내용을 의도적으로 넣는다면 그건 코드에 암세포를 주입하는거니 절대 자제하도록하자. 전역변수를 선언할 일이 있다면 정식으로 전역변수를 선언하면 될일이다. 저런식의 선언은 추후 버그발생시 디버깅을 극도로 어렵게하고 코드의 순서종속성도 생기게한다. 예제코드야 func() 아래에 gName을 찍으니까 정상출력되지 func() 함수가 호출되지 않는다면 전역에 gName 변수는 생성되지 않기때문에 에러가 발생되게 된다.


4. Strict Mode

이 외에도 자바스크립트의 유연한 문법, 또한 모호한 표준으로인해 개발자의 실수로인해 발생하는 에러를 언어단에서 잡아주지못하고 넘어가는 경우가 여럿 있을것이다. 이런 문제를 어느정도 해소시켜주기위해 ES5에서 도입된것이 Strict Mode다. mode라고해서 뭔가 추가적인 설정을 해야한다거나 하는 복잡함이 있을것 같은데 함수최상단에 그냥 문자열로 "use strict"; 라고만 써주면 된다.


function func(){
"use strict";
}


문자열로 설정하는게 뭔가 이상해보일수도 있으나 해당 부분은 하위호환을 매끄럽게 넘어가게해준다. ES5를 지원하지않아 Strict Mode를 사용할 수 없는 환경에서는 그냥 문자열하나 생성하고 아무런 문제없이 아래로 코드를 진행하게 할것이기 때문이다.


이 문자열 추가한거 하나로 위 문제들이 어떻게 되는지 살펴보자.


arguments 객체 수정

var test = function(arg){
"use strict";
arguments = [];
};

test("hello");


new 없이 호출하는 생성자

var Cons = function(name, age){
"use strict";
this.name = name;
this.age = age;
};

var obj = Cons("Lichking");


var 없이 선언하는 변수

var func = function(name){
"use strict";
gName = name;
};

func("LichKing");
console.log(gName);


결과는 직접 확인해보면 알것이다. 인터프리터언어라 사전에 에러를 발견하는건 여전히 어렵지만 최소한 런타임시에는 바로바로 에러가 발생하니 그나마 낫다. 거기에 포스팅을 작성하면서 알게된건데 내가 사용하는 IDE인 웹스톰에서는 IDE가 사전에 에러를 알려준다. IDE가 경고하는거에 불과하기때문에 무시하고 돌리면 실행은 되지만 IDE에 대단함에 다시한번 감탄을 하게됐다(new 없이 호출하는건 IDE조차 알 수 없으므로 그건 못잡지만^^;).


 



Strict Mode는 하위호환성까지 해치지않으므로 ES5를 지원하는 환경에서는 무조건 좋고 지원하지못해도 본전인 문법이다. 닥치고 넣으라고 권장한다. 

'Java Script & HTML' 카테고리의 다른 글

ES5 Array method  (0) 2017.05.13
유사배열객체  (0) 2017.05.06
Strict Mode  (0) 2017.04.30
setTimeout과 custom sleep  (4) 2017.02.12
AngularJS Filter 만들기  (0) 2017.02.03
put, delete 메서드로 submit 하기  (0) 2016.12.04
댓글
댓글쓰기 폼