A
がtrueでB
がfalseである理由を誰かに説明できますか? Bも真実であると期待していました。
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(function () {
console.log("B", this instanceof MyObject);
}());
}
new MyObject().test();
更新:ecmascript-6以降では、次のようにMyObjectを簡単に参照できるようにする矢印関数を使用できます。
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(() => {//a change is here, which will have the effect of the next line resulting in true
console.log("B", this instanceof MyObject);
})(); //and here is a change
}
new MyObject().test();
this
は特別です。これは、関数が呼び出されているオブジェクトを指します(最も一般的にはドット構文を介して)。
したがって、A
の場合、関数は新しいMyObject
オブジェクトの代わりに呼び出されています。 B
は、オブジェクトの代わりに明示的に呼び出されない別の関数にあるため、this
はデフォルトでグローバルオブジェクト(window
)に設定されます。
つまり、this
は、関数がどのように定義されているかではなく、関数がどのように呼び出されるであるかによって変化します。匿名関数(別の関数内で定義されている)を使用しているという事実は偶然であり、this
の値には影響しません。
無名関数の内部this
はグローバルオブジェクトです。
test
内では、これはメソッドが呼び出されたMyObject
のインスタンスです。
次のような関数を呼び出すときはいつでも:
somceFunction(); // called function invocation
this
is alwaysグローバルオブジェクト、またはundefined
がstrictモード(someFunction
がbind
で作成された場合を除く)** - 下記参照)
このような関数を呼び出すときはいつでも
foo.someMethod(); //called method invocation
this
はfoo
に設定されます
**EcmaScript5はbind
関数を定義します。これにより、this
の事前設定値を持つ関数を作成できます
したがって、この
var obj = { a: 12 };
var someFunction = (function () { alert(this.a); }).bind(obj);
someFunction();
someFucntion
がthis
と等しいobj
で呼び出され、アラート12.が表示されます。これは、関数について述べたルールの潜在的な例外であることを示していますとして呼び出された
someFunction();
常にthis
がグローバルオブジェクトと等しい(または厳密モードではundefined
)
無名関数では、this
はグローバルオブジェクト(ブラウザー環境ではwindow
)にバインドされます。
インスタンスにアクセスするにはさまざまな方法があります。
var self = this;
(function () {
console.log("B", self instanceof MyObject);
}());
または
(function () {
console.log("B", this instanceof MyObject);
}).call(this);
this
は、関数の呼び出し方法に基づいて設定されます。
匿名関数は通常の関数呼び出しであるため、this
はグローバルオブジェクトです。
(function() { ... }).call(this)
を使用して、明示的にthis
で呼び出します。