개발/Javascript

[You don't know JS] Part2 - 부록a. 다양한 환경의 자바스크립트

lanace 2020. 9. 6. 06:39

실제 서비스 환경에서 실행되는 자바스크립트 코드는 예상과 다르게 동작할 수 있다.

거의 항상 호스팅 환경의 콘텍스트에서 실행되기 때문인데,

다른 코드와 함께 실행하거나, 다른 유형의 엔진에서 실행되었을때 발생한다.

부록 A.1 ECMAScript


자바스크립트의 공식 명칭은 ECMAScript 이다.

브라우저환경이 아닌 node.js 나 Rhino 등의 환경에선 다음을 주의하자

  • 0123와 같은 8진수 리터럴은 느슨한 모드에서 사용할 수 있다.
  • window.escape() / window.unescape()를 이용하여 문자열 % 로 구분된 16진수 이스케이프 시퀀스 역변환이 가능하다.
  • String.prototype.substr은 String.prototype.substring 과 유사하지만 두번째 인자에 인덱스가 아닌 길이값이 들어간다.

부록 A.1.1 웹 ECMAScript


브라우저에만 있는것들이다.

  • <!— and —> 는 한줄짜리 유효한 주석 구분자이다.
  • String.prototype 추가
    • anchor
    • big
    • blink
    • bold
    • fixed
    • fontcolor
    • fontsize
    • italics
    • link
    • small
    • strike
    • sub

위의 메서드를 직접 쓸일은 드물고, 내장 DOM API 또는 사용자 유틸리티로 대체하자. 가능하면 사용 안하는게 좋다.

  • RegExp 의 확장
  • Function.prototype의 추가
    • arguments
    • caller

arguments와 caller는 권장하지 않으니 사용을 자제하자

부록 A.2 호스트 객체


var a = document.createElement('div');

typeof a;  // "object"
Object.prototpye.toString.call(a);  // "[object HTMLDivElement]"

a.tagName; // "DIV"

a는 일반 객체가 아니라 DOM 을 가리키는 특별한 호스트 객체이다.

내부 [[Class]] 값이 다르고, 미리 정의된 프로퍼티를 가진다.

False 객체가 강제변환 했을때 true가 아닌 false가 나오는 이유도 이와 같은 이유이다.

  • 호스트 객체를 다룰 때 조심해야 할 유의 사항을 정리한다.
  • toString() 같은 일반 객체의 내장 메서드에 접근할 수 없다.
  • 덮어쓸 수 없다.
  • 미리 정의된 읽기 전용 프로퍼티가 존재한다.
  • 다른 객체로 this를 재정의할 수 없는 메서드가 있다.
  • 기타 등등...

주변 환경에 따라 꼭 필요한 API들이 있다.

console 도 호스트 객체이다.

브라우저에선 콘솔창과 연결

노드에선 표준 입출력 시스템과 연결

부록 A.3 전역 DOM 변수


HTML에서 id로 할당해도 전역에 변수가 같이 할당됨

⇒ 예외처리시 전역객체를 사용하는건 오염이 있을 수 있음

⇒ 다른 HTML 코드와 겹치는지도 잘 확인해야됨

<div id="foo"></div>
if (typeof foo == "undefined") {
  // 실행 안됨
}

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

부록 A.4 네이티브 프로토타입


어떤일이 있어도 네이티브 프로토타입을 확장하지 말지어다.

  • 자바스크립트 고수 왈....

실제 예시

Array.prototype의 메서드나 프로퍼티가 없어서 추가한 경우, 내부 구현 로직이 달라서 어떤 사이드 이펙트를 발생시킬지 모름

// 넷스케이프 4에서의 push 메서드가 없어서 구현한 코드
Array.prototype.push = function(item) {
    this[this.length] = item;
}

다수의 아이템을 추가하는경우 문제가 된다.

주의

  1. 작성한 코드가 특정 환경에서만 실행될 것이라는 확신이 없는한 네이티브를 확장하지 말자.

  2. 무차별적인 확장은 피하자

     if (!Array.prototype.push) {
         Array.prototype.push = function () {
             // ... do something...
         }
     }
    • 웹 사이트에서 다수의 아이템을 추가하는 기능이 누락되었다면 오래전에 문제가 되었을 것이다.
    • 사용중인 라이브러리가 push에 대한 꼼수를 부리는 경우 문제는 여전하다.

그래서 어떻게?

어떤 환경에서 돌아가게 짜려면 많은 시간과 노력이 들어간다.

그렇다고 그냥 두자니 문제가 될 수 있다.

⇒ 답은 없지만 네이티브 프로토타입만 건들이지 않는다면 문제가 심각해지는건 막을 수 있다.

부록 A. 4.1 심/폴리필


구 버전의 환경에서 없는 기능을 추가해 주는것을 폴리필 이라 한다.

다만 새로운 일부 표준 기능은 폴리필/프로리필로 대체할 수 없다.

⇒ 그렇다면 사용하지 말아야 되는건 아닌가?

⇒ 아직도 논란중이다.

결론적으로 방어코드를 작성하고, 위협 요소에 대해 가급적 문서를 작성하여 의도를 명확히 밝히는것이 좋다.

부록 A. 5