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


85

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

例:

(function () {
    "use strict";

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

フィドルでテストする:http//jsfiddle.net/Pyr5g/1/ ロガー(firebug)をチェックしてください。


4
これは無名関数とは関係がなく、呼び出しメソッドとは関係がないことに注意してください。この変更されたフィドルを参照してください(コンソールログを確認してください)。
Phrogz 2012年

@Phrogz:これは混乱の原因かもしれません。それを指摘してくれてありがとう。
T.ユンハンス

回答:


101

これは、ECMAscript 262エディション5までconstructor pattern、を使用している人がnewキーワードの使用を忘れた場合に大きな混乱があったためです。newES3でコンストラクター関数を呼び出すときに使用するのを忘れた場合は、(ブラウザーで)thisグローバルオブジェクトを参照し、window変数でグローバルオブジェクトを壊してしまいます。

それはひどい振る舞いだったので、ECMAの人々はただに設定thisすることにしましたundefined

例:

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

最後の行はES5strictでエラーをスローします

"TypeError: this is undefined"

(これははるかに優れた動作です)


4
意味あり。ステートメントをバックアップするための参照がありますか?
ロブW

1
@RobW:自分で検索する必要がありますが、ダグラス・クロックフォードが何度か聞いたところ、これがその決定の理由でした。
jAndy 2012年

1
これは、JavaScript:CrockfordによるThe GoodPartsで言及されています。詳細に説明されています。ただし、ECMAの決定についてではありません。
madr 2012年

1
これが、strictモードがデフォルトでこれをundefinedに設定する論理的な理由です。もう1つの論理的な理由は効率です。もう1つの論理的な理由は、this === window混乱を招き、グローバルスコープをトークンとして関数にリークすることです
Raynos 2012年

2
@jAndy:答えてくれてありがとう。意味あり。また、javascriptweblog.wordpress.com / 2011/05/03 /でこれに対する変更の簡潔な説明を見つけました… : "特に、呼び出すまたは適用する最初の引数がnullまたは未定義の場合、呼び出された関数のこの値グローバルオブジェクトに変換されません。」
T.ユンハンス

15

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

詳細については、
https://developer.mozilla.org/en/JavaScript/Strict_modeをご覧ください。


@samuelでは、厳密モードでウィンドウオブジェクトに変数を割り当てるにはどうすればよいですか?
ヌルポインタ

8

このスタックオーバーフローの回答によると、this匿名関数.call(this)の最後で呼び出すだけで、匿名関数内で使用できます。

(function () {
    "use strict";

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

4
この場合、オブジェクトにthisなることに注意してくださいWindow。これは望ましくない場合があります
Ninjakannon 2017

この答えは、尋ねられた質問を説明していません。
AnveshChecka19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.