web-dev-qa-db-ja.com

strictを使用すると、匿名関数の「this」が未定義になるのはなぜですか?

厳密モードでjavascriptを使用するときに、匿名関数のthisが未定義なのはなぜですか?なぜこれが理にかなっているのか理解していますが、具体的な答えが見つかりませんでした。

例:

(function () {
    "use strict";

    this.foo = "bar"; // *this* is undefined, why?
}());

フィドルでテスト: http://jsfiddle.net/Pyr5g/1/ ロガーをチェックアウトします(firebug)。

80
TJ.

これは、ECMAscript 262 edition 5まで、constructor patternnewキーワードの使用を忘れました。 ES3でコンストラクター関数を呼び出すときにnewを使用するのを忘れた場合、thisはグローバルオブジェクト(ブラウザーではwindow)を参照し、グローバルオブジェクトを変数で上書きします。

それはひどい行動だったので、ECMAの人々はthisundefinedに設定することにしました。

例:

function myConstructor() {
    this.a = 'foo';
    this.b = 'bar';
}

myInstance     = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance  = myConstructor(); // oh my gosh, we just created a, and b on the window object

最終行は、ES5 strictでエラーをスローします

"TypeError: this is undefined"

(これははるかに良い動作です)

94
jAndy

呼び出された関数のコンテキストに入る前にthisオブジェクトをラップまたは変更する「ボクシング」と呼ばれるメカニズムがあります。この場合、関数をオブジェクトのメソッドとして呼び出していないため、thisの値はundefinedである必要があります。この場合、非厳密モードの場合、これはwindowオブジェクトに置き換えられます。 strictモードでは常に変更されないため、ここでundefinedになります。

で詳細を見つけることができます
https://developer.mozilla.org/en/JavaScript/Strict_mode

15
Samuel Rossille

このスタックオーバーフローの答え によれば、thisを匿名関数内で使用できます。そのためには、最後に.call(this)を呼び出すだけです。

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);
5
ReverseTales