関数がオブジェクトのメソッドとして呼び出される場合、これはオブジェクトを指します:
var obj = { a: 1, getA: function(){ alert ( this === obj ); //输出:true alert ( this.a ); //输出: 1 }};obj.getA();
として呼び出された場合、これは常にグローバル オブジェクトを指します。ブラウザー JavaScript では、このグローバル オブジェクトはウィンドウ オブジェクトです。
window.name = 'globalName';var getName = function(){ return this.name;};console.log( getName() ); //输出:globalName
または:
window.name = 'globalName';var myObject = { name: 'sven', getName: function(){ return this.name; }};var getName = myObject.getName;console.log( getName() ); //globalName
たとえば、div ノードのイベント関数内には、コールバックが通常の関数として呼び出される場合、これがローカル コールバック メソッドとして存在します。コールバック内は window を指しますが、多くの場合、div ノードを指すようにしたい場合があります。次のコードを参照してください。
<html> <body> <div id="div1">我是一个div</div> </body> <script> window.id = 'window'; document.getElementById( 'div1' ).onclick = function(){ alert( this.id ); //输出: 'div1' var callback = function(){ alert( this.id ); //输出:'window' } callback(); }; </script></html>
現時点では簡単な解決策があり、変数を使用して、 div ノードの参照:
document.getElementById( 'div1' ).onclick = function(){ var that = this; //保存div的引用 var callback = function(){ alert( that.id ); //输出:'div1' } callback();};
ECMAScript5 の厳密モードでは、この場合、これはグローバル オブジェクトを指すのではなく、未定義を指すように規定されています:
function func(){ "use strict" alert ( this ); //输出:undefined}func();
new 演算子を使用して関数を呼び出すと、関数は常にオブジェクトを返します。通常、コンストラクター内の this は返されたオブジェクトを指します。
var myClass = function(){ this.name = 'sven';};var obj = new myClass();alert ( obj.name ); //输出:sven
ただし、new を使用してコンストラクターを呼び出す場合、コンストラクターが object 型のオブジェクトを明示的に返す場合、この操作の結果は最終的にこのオブジェクトを返します。
var myClass = function(){ this.name = 'sven'; return { //显式地返回一个对象 name: 'anne' }};var obj = new myClass();alert ( obj.name ); //输出:anne
コンストラクターが明示的にデータを返さない場合、または非オブジェクト型のデータを返す場合、上記の問題は発生しません:
var myClass = function(){ this.name = 'sven'; name = 'anne'; return name; //返回string类型};var obj = new myClass();alert ( obj.name ); //输出:sven
Function.prototype.call または Function.prototype.apply を使用して、受信関数の this を動的に変更します:
var obj1 = { name: 'sven', getName: function(){ return this.name; }};var obj2 = { name: 'anne'};console.log( obj1.getName() ); //输出: svenconsole.log( obj1.getName.call( obj2 ) ); //输出: anne
document.getElementById のメソッド名が長すぎるため、短い関数に置き換えようとします:
var getId = function( id ){ return document.getElementById( id );};getId( 'div1' );
なぜ次のより単純なメソッドを使用できないのか考えたかもしれません:
var getId = document.getElementById;getId( 'div1' );
ブラウザで次のコードを実行します:
<html> <body> <div id="div1">我是一个div</div> </body> <script> var getId = document.getElementById; getId( 'div1' ); </script></html>
このコードは例外をスローすることがわかります。これは、多くのエンジンの document.getElementById メソッドの内部実装で必要とされるためです。この this は本来、ドキュメント オブジェクトのプロパティとして getElementById メソッドが呼び出されるときに、ドキュメントを指すことが期待されていました。メソッド内の this はドキュメントを指します。
しかし、getId を使用して document.getElementById を参照し、getId を呼び出した後は、関数内のこれは元のドキュメントではなくウィンドウを指す通常の関数呼び出しになります。
apply を使用してドキュメントを getId 関数に渡し、これを「修正」することができます:
document.getElementById = (function( func ){ return function(){ return func.apply( document, arguments ); }})(document.getElementById);var getId = document.getElementById;var div = getId( 'div1');alert( div.id ); //输出:div1
参考: 「JavaScript の設計パターンと開発プラクティス」 "