グローバルスコープ
関数呼び出し
メソッド呼び出し
コンストラクター呼び出し
これを明示的に設定する
よくある誤解
メソッドの代入式
JavaScriptにはこれを処理するメカニズムは他の言語とはまったく異なります。 5 つの異なるケースにおいて、これは異なることを示しています。
グローバル スコープ
this;
これがすべてのスコープで使用される場合、グローバル オブジェクトを指します。
関数呼び出し
foo();
ここでも、これはグローバルオブジェクトを指します。
メソッド呼び出し
test.foo();
この例では、これはテスト オブジェクトを指します。
コンストラクターを呼び出す
new foo();
関数が new キーワードとともに使用される傾向がある場合、この関数をコンストラクターと呼びます。 関数内では、これは新しく作成されたオブジェクトを指します。
thisを明示的に設定する
function foo(a, b, c) {} var bar = {}; foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示 foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3
Function.prototypeでcallまたはapplyメソッドを使用する場合、関数内のthisは関数呼び出しの最初のパラメータとして明示的に設定されます。
そのため、関数呼び出しのルールは上記の例では適用されなくなり、これは foo 関数の bar に設定されます。
よくある誤解
ほとんどの状況は真実ですが、最初のルール (翻訳者注: これは 2 番目のルールを参照する必要があります。つまり、関数を直接呼び出す場合、これはグローバル オブジェクトを指します) は次のとおりです。 JavaScript 言語は実際に使用されることがなかったため、JavaScript 言語の設計ミスがまた発生したと考えられています。
Foo.method = function() { function test() { // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象) } test(); }
よくある誤解は、テスト中の this が Foo オブジェクトを指すということですが、実際にはそうではありません。
テストで Foo オブジェクトへの参照を取得するには、Foo オブジェクトを指すメソッド関数内にローカル変数を作成する必要があります。
Foo.method = function() { var that = this; function test() { // 使用 that 来指向 Foo 对象 } test(); }
これは私たちがランダムに付けた名前にすぎませんが、この名前は外部のこのオブジェクトを指すために広く使用されています。 「クロージャ」セクションでは、これをパラメータとして渡すことができることを確認しました。
注: オブジェクトのリテラル宣言構文では、オブジェクト自体を指すためにこれを使用することはできません。 したがって、var obj = {me: this} の me は obj を指しません。これは、上記の 5 つの状況でのみ現れるためです。 翻訳者注: この例では、ブラウザで実行すると、obj.me は window オブジェクトと同じになります。
メソッドの代入式
もう一つ奇妙に見えるのは、メソッドを変数に代入する関数エイリアスです。
var test = someObject.methodTest; test();
上記の例では、test は通常の関数のように呼び出されるため、関数内の this は someObject オブジェクトを指しなくなります。
この遅延バインディング機能は不親切に見えますが、実際にはプロトタイプの継承が依存する土壌に基づいています。
function Foo() {} Foo.prototype.method = function() {}; function Bar() {} Bar.prototype = Foo.prototype; new Bar().method();
メソッドが呼び出されるとき、これは Bar のインスタンス オブジェクトを指します。
上記は JavaScript 上級シリーズの内容です。この動作原理の詳細については、PHP 中国語 Web サイト (m.sbmmt.com) をご覧ください。