2017-10-02 10 views
1

私はjavascript 'this'と疑問を持っています。私は、 'これ'は呼び出し関数のオブジェクトを参照していることを理解しています。例1では、私たちは)(obj.bar呼び出している場合は、なぜthis.x = 4javascriptでネストされた関数の 'this'キーワードの混乱

var x = 4, 
obj = { 
    x: 3, 
    bar: function() { 
     var x = 2; 
     setTimeout(function() { 
      var x = 1; 
      alert(this.x); 
     }, 1000); 
    } 
}; 
obj.bar(); 

出力:4

次のコードでは、なぜthis.x = 3と1以降:

var x = 3; 
var foo = { 
    x: 2, 
    baz: { 
     x: 1, 
     bar: function() { 
      return this.x; 
     } 
    } 
} 
var go = foo.baz.bar; 
alert(go()); 
alert(foo.baz.bar()); 

出力:関数を作成するとき 3,1

+0

これは、別の関数( 'setTimeout'に渡される関数)の中で呼び出すためです。 –

答えて

3

あなたは非常にトップレベルで変数を宣言するとき、あなたはwindowオブジェクト内のグローバル変数を作成しているに等しいfoo.baz.xthis.x equivilentを作り、何を参照するかですので、コンテキストは、foo.bazです。トップレベルのキーワードthisは、windowを指します。

var x = 4; // same as `window.x = 4`; 
console.log(x); // same as `console.log(this.x)`; 

あなたがobj.bar()を呼び出すと、thisキーワードがbarの内側objを指します。しかしsetTimeoutの中には、別のthisがあります。これは、setTimeoutに渡すコールバックの発信者を参照するものです。この呼び出し元はthisの値を指定しないので、代わりにwindowオブジェクトになります。したがって、このコードで:

setTimeout(function() { 
    var x = 1; 
    alert(this.x); 
}, 1000); 
this.x

は、グローバルスコープで上記に定義した通りである4window.x、同じです。あなたは、その関数がどこから来たの文脈失う関数を変数に割り当てるあなたの第二の例をアドレッシング

、:あなたはgo()通知を呼び出すとき

var go = foo.baz.bar; 

が今では、コール内にドットがない、これ暗黙的にthisが存在しないことを意味する、明示的なオブジェクトアクセスがないことを意味します。この場合、あなたはまだcallを使用してthisを渡すことができます:あなたはuse strictで、これらの問題の多くを回避することができ

// outputs `3` because `this` is `window`, and `window.x` is `3` 
// as declared in the global scope 
alert(go()); 

// Will output `2` because `this` is `foo` 
alert(go.call(foo)); 

// Will output `1` because `this` is `foo.baz` 
alert(go.call(foo.baz)); 

// Will output `1` because the implicit value of `this` is `foo.baz` 
// since we have an explicit object access in this function call 
alert(foo.baz.bar()); 

。 strictモードでは、オブジェクトにデフォルト設定する代わりに、thisが明示的または暗黙的に定義されていないときは未定義になります。

3

thisが決定されていません。 がいつ関数を呼び出すかが決定されます。

setTimeoutの場合、一定の時間が経過すると、関数は単に青色から実行されています。コンテキストがないため、ブラウザはグローバルコンテキストで関数を呼び出します。あなたはx=4のグローバル変数を宣言しているので、this.xと同じです。 (スクリプトの先頭に"use strict";を追加して)strictモードを使用した場合、thisはsetTimeoutの場合は未定義となり、エラーが発生します。

go()を呼び出すと、コンテキストのないスタンドアロンの機能があるため、グローバルコンテキストで再度呼び出されます。これにより、グローバルx = 3が使用されます。

foo.baz.bar()に電話すると、最終的にコンテキストがあります。それはthis 1.

関連する問題