Web フロントエンドの同僚は全員、 document.getElementById に精通しています。開発プロセスでは、xx というページ ID を持つ要素を取得するためにこれを使用する必要があることがよくあります。 ベテランの 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 を定義する
関数 show(){alert(this.name);}
// name 属性を使用して p オブジェクトを定義する
var p = {名前:'ジャック'};
show.call(p); // -> 'ジャック'
show(); // -> ''
show.call(null); // -> ''<BR>
show の実装はこれに依存していることがわかります(簡単に言うとメソッド本体でこれを使用しています)。そのため、呼び出し時の環境(実行コンテキスト)に name 属性がないと期待した結果が得られません。
つまり、IE6/7/8 は document.getElementById を実装するときにこれを使用しませんが、IE9/Firefox/Safari/Chrome/Opera ではこれを使用する必要があります。ここで、これはドキュメント オブジェクトです。メソッド2を直接呼び出した場合、内部のthisはwindowオブジェクトとなるため、メソッド2ではFirefox/Safari/Chrome/OperaのIDを元に要素を正常に取得することができません。
document.getElementByIdの実行環境をwindowではなくdocumentに変更すると普通に$が使えるようになります。次のように
次のようにコードをコピーします。
// document.getElementById を修正
document.getElementById = (関数(fn){
戻り関数(){
fn.apply(ドキュメント,引数)を返します;
};
})(document.getElementById);
// 修復後、$ に値を代入すると、$ は正常に使用できるようになります。
var $ = document.getElementById;
ここでも、ECMAScript5 の関数の新しいバインド メソッドで同じ効果を実現できます。
次のようにコードをコピーします。
// 方法 3
var $ = document.getElementById.bind(document);
ただし、現在、方法 3 は IE9/Firefox/Chrome/ でのみサポートされています。
getElementById の状況を分析すると、次のメソッドがさまざまなブラウザーで異なる理由が簡単に理解できます。
次のようにコードをコピーします。
var prinf = ドキュメント.ライト;
prinf('<h3>Test prinf</h3>'); // IE6/7/8 は実行できますが、他のブラウザはエラーを報告します。
var prinfln = document.writeln;
prinfln('<h3>Test prinfln</h3>'); // IE6/7/8 は実行できますが、他のブラウザではエラーが報告されます。
var reload = location.reload;
reload(); // IE6/7/8 は実行できますが、他のブラウザではエラーが報告されます。
var go = 履歴.go;
go(-2); // IE6/7/8 は実行できますが、他のブラウザではエラーが報告されます。