모든 웹 프런트 엔드 동료는 document.getElementById에 매우 익숙합니다. 개발 과정에서 페이지 ID가 xx인 요소를 얻기 위해 이를 사용해야 하는 경우가 종종 있습니다. JS의 베테랑 라이브러리인 Prototype이 인기를 얻었기 때문에 모두가 이렇게 단축하는 것을 좋아합니다.
다음과 같이 코드 코드를 복사합니다.
// 방법 1
함수 $(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 정의
함수 표시(){alert(this.name);}
//name 속성을 사용하여 p 객체를 정의합니다.
var p = {이름:'잭'};
show.call(p); // -> '잭'
쇼(); // -> ''
show.call(null); // -> ''<BR>
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 = (함수(fn){
반환 함수(){
return fn.apply(문서,인수);
};
})(document.getElementById);
// 수리 후 $에 값을 할당하면 $를 정상적으로 사용할 수 있습니다.
var $ = document.getElementById;
다시 말하지만, ECMAScript5의 함수에 대한 새로운 바인딩 방법은 동일한 효과를 얻을 수 있습니다.
다음과 같이 코드 코드를 복사합니다.
// 방법 3
var $ = document.getElementById.bind(document);
그러나 현재 방법 3은 IE9/Firefox/Chrome/에서만 지원됩니다.
getElementById의 상황을 분석해 보면 브라우저마다 다음 메소드가 다른 이유를 쉽게 이해할 수 있습니다.
다음과 같이 코드 코드를 복사합니다.
var prinf = document.write;
prinf('<h3>Test prinf</h3>'); // IE6/7/8이 실행될 수 있지만 다른 브라우저에서는 오류가 보고됩니다.
var prinfln = document.writeln;
prinfln('<h3>Test prinfln</h3>'); // IE6/7/8이 실행될 수 있지만 다른 브라우저에서는 오류가 보고됩니다.
var reload = 위치.reload;
reload(); // IE6/7/8은 실행될 수 있지만 다른 브라우저에서는 오류가 보고됩니다.
var go = History.go;
go(-2); // IE6/7/8이 실행될 수 있지만 다른 브라우저에서는 오류가 보고됩니다.