본문 바로가기

Javascript

[JavaScript] ECMAScript

반응형

 

자바스크립트 프로그램은 거의 항상 호스팅 환경의 콘텍스트에서 실행되므로 예측하기 어려운 부분이 어느정도 있다.

예를 들어, 작성한 코드를 다른 소스 코드와 함께 실행하거나,
(브라우저 이외의) 다른 유형의 자바스크립트 엔진에서 실행하면 예상과 다르게 작동할 수 있다.

 

이번 내용은 이 문제를 간략하게 다루고자 한다.

 

ECMAScript

자바스크립트의 공식적인 언어 명칭이 ECMAScript(ECMA는 표준 관리 주체 기관을 뜻함)라는 사실은 잘 알려져 있지 않다.

자바스크립트는 ECMAScript 언어의 상품명으로 통용되며, 더 정확하게는 명세의 브라우저 구현체이다.
(필자도 이번에 알았다..=.=)

 

아래의 내용은 주요 호환성 차이를 열거한 내용이다.

* 0123(10진수의 83)와 같은 8진수 리터럴은 느슨한 모드에서 사용할 수 있다.

* window.escape() / window.unescape() 를 이용해 '문자열 <> %기호로 구분된 16진수 이스케이프 시퀀스 변환/역변환'이 가능하다.

* String.prototype.substr은 String.prototype.substring과 유사하나, 두번째 인자는 종료 인덱스가 아닌 길이(문자열의 문자 개수)를 의미한다.

 

웹 ECMAScript

아래의 내용은 다른 브라우저와의 호환을 위한 브라우저의 '필수 요건'이나, 이제는 거의 쓰지 않는 것들이므로 참고만 하자.

* <!-- -->

    한 줄짜리 유효한 주석 구분자

* String.prototype 의 anchor(), big(), blink(), bold(), fixed(), fontcolor(), fontsize(), italics(), link(), small(), strike(), sub()

  ⇢ 이 메서드들은 직접 쓸일이 매우 드물고, 내장 DOM API 또는 사용자 정의 유틸리티로 대체하여 가급적 사용을 비권장함

* RegExp 의 확장

* Function.prototype 의 arguments, arguments.caller

   이 객체들은 가능한 사용을 비권장함

 

호스트 객체

자바스크립트 변수 규칙 중 자동 정의 변수인 호스트 객체(내장 객체/함수 포함)에 관해서라면 예외 사항이 있다.

 

예시)

var a = document.createElement("div");
typeof a; // "object"

Object.prototype.toString.call(a); // "[object HTMLDivElement]"
a.tagName // "DIV"

 

위 예시처럼 a는 DOM 요소를 가리키는 특별한 호스트 객체이다. 따라서 미리 정의된 프로퍼티를 가진다.

 

따라서 호스트 객체를 다룰때 조심해야 할 유의사항을 정리하여 사용하여야한다.

* toString() 같은 일반 객체의 내장 메서드에 접근한 수 없다.

* 덮어쓸 수 없다.

* 미리 정의된, 읽기 전용 프로퍼티를 가진다.

* 다른 객체로 this를 재정의할 수 없는 메서드가 있다.

* 기타 등등..

 

자바스크립트 코드가 주변 환경과 잘 어울리고 제대로 실행되려면 호스트 객체가 꼭 필요하는데,
이때 이들이 어떻게 작동하는지 세심하게 살펴야 한다.

 

전역 DOM 변수

id 속성으로 DOM 요소를 생성해도 같은 이름을 가진 전역 변수가 생성된다.

 

예시)

<div id="test"></div>
if (typeof test == "undifined") {
	test = 5959;
}

console.log(test); // HTML 요소

 

위 예시처럼 HTML 페이지 역시 전역 변수를 생성할 수 있어 조심하지 않으면 기존의 체크 로직은 생각지 못한 이슈를 발생시킬 수 있다.

따라서 이런 이유 때문에라도 가급적 전역 변수 사용은 자제하는 편이 좋고, 사용할 수 밖에 없다면 충돌하지 않게 유일한 이름으로 변수를 명명하자.

 

네이티브 프로토타입

Array.prototype의 메서드나 프로퍼티 중 본인이 찾는 것이 없어 추가 구현해야하는 경우에 이미 명세에 포함되어있을 경우가 매우 높다.

그럼에도 불구하고 내가 직접 확장을 한다면 충돌은 피할 수 없을 것이다.

그러니 아래의 내용을 생각하고, 문제가 없다고 생각하면 그 때 생성하도록 한다.

 

( 1 ) 내가 짠 코드가 특정 환경에서만 실행될 것이라는 절대적 확인이 없는 한 네이티브를 확장하지 말자.
       직접 확장한 네이티브는 위험해서 이후에 발생하는 리스크를 감수해야한다.

( 2 ) 실수로 네이티브를 덮어쓸지 모르니 무차별적인 확장은 피하자.

       내가 직접 작성한 코드가 의존하는 모든 전용 내장 기능은 재정의할 수 없기 때문에 반드시 네이티브를 확장하지 않아도 된다.

즉, 네이티브 프로토타입을 확장하지 않으면 안전한 코드를 가져갈 수 있다.

 

심/폴리필

구 버전(표준 명세를 준수하지 않는) 환경은 바뀔 가능성이 거의 없기 때문에 네이티브를 확장시켜도 안전한 유일한 장소로 꼽힌다.

만약 특정 명세가 정해져있고 그 기능이 정의되어 안전하게 사용할 수 있다면 이런 코드를 보통 '폴리필(Polyfill) 또는 심(sblm)'이라고 한다.

 

즉, 최신 명세에 미처 반영되지 못한 옛날 브라우저 환경을 패치할 용도로 현재 코드 베이스에 포함시킬 수 있는 폴리필은

지원할 모든 환경별로 예측 가능한 코드를 생성할 아주 훌륭한 수단이다.

 

만약 어떤 표준의 출시가 임박해 이미 명칭과 작동 방식에 대해 구체적인 논의가 진행되어 많은 사람들이 수긍한 상태에서

앞으로의 표준에 맞추기 위해 사전 제작된 폴리필을 '프롤리필(prollyfill, Probably Fill)'이라고도 한다.

 

다만, 새로운 일부 표준 기능은 완전히 폴리필/프롤리필로 대체할 수 없다는 걸 조심해야한다.

물론 방어적인 코드(if문)를 통해 코드를 작성하고 위험 요소에 대해 문서를 잘 작성한다고 해도 완전히 안전한 것은 아니다.

폴리필 코드(네이티브 확장한 코드)가  다른 코드와 함께 실행되는 환경에서는 다르게 동작할 수 있는 점을 인지하고 작업하자.

 

<Script>들

브라우저로 접속하는 대다수의 웹사이트나 애플리케이션은 다수의 자바스크립트 코드 파일로 구성되고, 

이 파일들은 대게 <script src=...></script> 태그로 하나씩 페이지를 읽거나 인라인 형태로 <script>...</script> 사이에 코드를 넣기도 한다.

이 경우 대부분의 경우 저마다 각자의 자바스크립트 프로그램으로 작동한다.

 

프로그램들이 서로 공유하는 건 단일 전역 객체(브라우저는 window)가 유일하다.

여러 파일들이 공유된 네임스페이스에 자신의 코드를 덧붙여서 상호 작용을 할 수 있는 것도 이 때문이다.

그러나 전역 변수 스코프는 파일을 넘나들면서 호이스팅하지는 않기 떄문에 <script src=...></script> 라던가 <script>...</script> 라던가 상관없이 작동하지 않는다.

 

작동하지 않는 예시 )

<script> foo(); </script>
<script>
	function foo() {...}
</script>

 

작동하는 예시 )

<script> 
	foo();
	function foo() {...}
</script>

<script>
	function foo() {...}
</script>
<script> 
	foo();
</script> 

 

또한 한 스크립트에서 에러(인라인/외부 로딩 둘 다)가 나면 독립적인 개발 자바스크립트로 해당 프로그램만 실패 후 중단되며,

다른 후속 스크립트는 아무런 영향을 받지 않고 (여전히 전역 객체를 공유한 상태로) 실행된다.

 

스크립트 요소를 코드에서 동적으로 생성한 후 페이지 DOM에 주입하는 기법도 있다.

그러나 이제는 인라인 코드(<script>...</script>) 주변에 HTML 스타일이나 X(HT)ML 스타일의 주석을 쓰는 코딩 습관은 권장하지 않는다.

 

비권장하는 코딩 스타일 예시 )

<script>
	var code = "<sc"+"ript>"+"alert('Hello world')"+"</sc"+"ript>";
</script>

<script>
<!--
	alert('Hello world');
//-->    
</script>

 

 


[참고] You Don't Know JS 타입과 문법, 스코프와 클로저 - 카일 심슨

 

반응형

❥ CHATI Github