3 つのケースすべてを個別に見てみましょう。
function myFunction()
{
var value = 0;
}
ここでは、関数のスコープで変数を宣言しています。関数が呼び出されるたびに、変数が作成されます (そしてメモリが割り当てられます)。関数が戻ると、変数はスコープ外になります。変数value
にはフラグが立てられ、GC されます。この関数のスコープより「高い」スコープからスコープにアクセスすることはできません...この関数がそのスコープ内で関数を定義した場合、その関数は変数にアクセスできますvalue
(詳細についてはクロージャーを調べてください)。結論: 変数は関数が呼び出されたときのみ存在し、関数が戻った後は存在しません。
function myFunction()
{
this.value = 0;
}
ここでは、コンストラクター、メソッド、イベント ハンドラー、または上記のすべての組み合わせである関数を定義しています。this
関数が呼び出されるコンテキストを指す参照です。このコンテキストは「アドホック」と判断され、異なる場合があります。
myFunction();// global scope, this points to window
var anObject = {method: myFunction};
anObject.method();//called in the object's context, this points to object
console.log(abObject.value);//logs 0
var instance = new myFunction();//as constructor
console.log(instance.value);//logs 0
document.getElementById('anInputField').onclick = myFunction;//on click, value will be set to 0
最後のケースでは:
function myFunction()
{
this.value = 0;
}
myFunction.value = 0;
次のように書いていれば、何の違いもありませんでした。
function myFunction()
{}
myFunction.value = 0;
上で説明したように、:this
関数が呼び出された時点でのコンテキストが何であれ参照するためです。実際、これは である必要はありませんmyFunction
: 多くの場合、そうではありません:
var anObject = {method: myFunction};
myFunction.value = 101;//myFunction.value is changed
anObject.method();
console.log(anObject.value);//0 -> the function still sets the value property to 0
関数内の関数のプロパティにアクセスする場合、最も簡単な方法は、他のオブジェクトと同じようにその関数を参照することです。
function myFunction()
{
this.value = myFunction.value;
}
myFunction.value = 101;
注意:
フレンドリーな警告:this
グローバルをチェックせずに関数で使用するのはあまり安全ではありません...関数が明示的なコンテキストなしで呼び出された場合、JS はデフォルトwindow
でグローバル ( ) オブジェクトを使用します。これは、たまたま指しているオブジェクトにプロパティを割り当てるすべての行が、グローバル変数を設定することを意味します。this
function myFunction()
{
this.foo = 'bar';
}
myFunction();
console.log(window.foo);//logs bar EVIL GLOBAL
グローバルオブジェクトがグローバルで雑然とするのを防ぐいくつかの方法:
function mySafeFunction()
{
'use strict';//throws errors, check MDN
//this defaults to null, instead of window
impliedGlobal = 'Error';//doesn't work
this.onGlobal = 'Error';//null.property doesn't work
}
//same goes for constructors, but a more precise check can be used, too (and works on older browsers)
function SafeConstructor()
{
if (!(this instanceof SafeConstructor))
{//this doesn't point to SafeConstructor if new keyword wasn't used
throw new Error('Constructor wasn\'t called with new keyword');
//or "correct" the error:
return new SafeConstructor();
}
console.log(this);// will always point to the SafeConstructor object
}