모든 웹 프런트엔드 동료는 document.getElementById에 매우 익숙합니다. 개발 과정에서 페이지 ID가 xx인 요소를 얻기 위해 이를 사용해야 하는 경우가 종종 있습니다. JS 라이브러리의 베테랑인 Prototype이 인기를 얻었기 때문에 다들 이렇게 줄여서 사용하는 것을 좋아합니다
// 방법 1
function $(id){ return document.getElementById(id); }
혹시 왜 아래와 같은 방식이 아닌 이렇게 쓰는지 생각해보신 적 있으신가요?
// 방법 2
var $ = document.getElementById;
$를 이렇게 작성하는 것이 더 간결하고 명확합니다. 문서 메소드 getElementById를 $ 변수에 할당하고 $를 사용하여 페이지 ID가 xx입니다. 실제로 방법 2는 IE6/7/8(IE9에서 일부 변경 사항 있음)에서는 가능하지만 Firefox/Safari/Chrome/Opera에서는 가능하지 않습니다. 여러분도 직접 테스트해 보시기 바랍니다.
Firefox/Safari/Chrome/Opera가 방법 2를 통해 이를 얻을 수 없는 이유는 이러한 브라우저에서 getElementById 메소드의 내부 구현이 이(문서)에 의존해야 하는 반면 IE는 이를 요구하지 않기 때문입니다. . 즉, 방법 2는 Firefox/Safari/Chrome/Opera에서 호출할 때 이것이 누락되었다고 말합니다. 다음은 간단한 예입니다
// 함수 정의 show
function show(){alert(this.name);}
// 정의 이름 속성이 있는 p 객체
var p = {name:'Jack'}
show.call(p) // -> 'Jack'
show(); > ''
show.call(null); // -> ''
show 구현이 이에 의존한다는 것을 알 수 있습니다. 메소드 본문에서 사용됨) 호출 환경(실행 컨텍스트)에 name 속성이 없으면 예상한 결과를 얻을 수 없습니다.
즉, IE6/7/8에서는 document.getElementById를 구현할 때 이를 사용하지 않지만, IE9/Firefox/Safari/Chrome/Opera에서는 이것이 문서 개체인 경우 이를 사용해야 합니다. 메소드 2를 직접 호출할 경우 내부 this는 window 객체이므로 Firefox/Safari/Chrome/Opera의 ID를 기준으로 메소드 2는 정상적으로 요소를 얻을 수 없습니다.
document.getElementById의 실행 환경을 window가 아닌 document로 변경하면 $를 정상적으로 사용할 수 있습니다. 다음과 같이
// document.getElementById 수정
document.getElementById = (function(fn){
return function(){
return fn.apply(document,arguments);
};
})(document.getElementById);
// 복구 후 $에 값을 할당하면 $를 정상적으로 사용할 수 있습니다.
var $ = document.getElementById
다시 함수에 대한 새로운 바인딩 방법입니다. ECMAScript5에서는 동일한 효과를 얻을 수 있습니다
// 방법 3
var $ = document.getElementById .bind(document)
그러나 현재 방법 3은 IE9/Firefox/Chrome/에서만 지원됩니다.
getElementById의 상황을 분석해 보면 다양한 브라우저에서 다음 메소드의 차이가 나타나는 이유를 쉽게 알 수 있습니다.
var prinf = document.write
prinf('
Test prinf
') // IE6/7/8 실행 가능, 다른 브라우저에서는 오류 보고
var prinfln = document.writeln
prinfln('Test prinfln
') // IE6/7/8 실행 가능, 기타 브라우저에서 오류 보고
var reload = location.reload;
reload(); // IE6/7/8은 실행 가능, 다른 브라우저에서는 오류 보고
var go = History.go;
go(-2); // IE6/7/8은 실행할 수 있지만 다른 브라우저에서는 오류가 보고됩니다.