} ;
GetValue(fooBarReference); // 関数オブジェクト "bar"
では、最も重要な意味で、参照型の値は関数コンテキストでの this の値にどのように関連しているのでしょうか?この関連付けのプロセスがこの記事の中心です。 (与えられた瞬間がこの記事の中心です。) 関数コンテキストで this の値を決定するための一般的な規則は次のとおりです:
関数コンテキストでは、this の値は呼び出し元によって提供され、次によって決定されます。関数の呼び出し方法。呼び出し括弧 () の左側が参照型値の場合、これは参照型値の基本オブジェクトに設定されます。それ以外の場合 (参照型とは異なるその他のプロパティ)、this の値は次のようになります。ヌル。ただし、this の値が null である実際の状況はありません。this の値が null の場合、その値は暗黙的にグローバル オブジェクトに変換されるからです。
例を見てみましょう:
function foo () {
return this;
}
foo(); // global
呼び出し側の括弧の左側が参照型であることがわかります。値 (foo は識別子であるため):
var fooReference = {
base : global,
propertyName: 'foo'
};
同様に、これも参照型の基本オブジェクトに設定されます。それがグローバルオブジェクトです。
同様に、プロパティ アクセサーを使用します。
var foo = {
bar: function () {
return this;
}
} // foo
同様に、ベースが foo オブジェクトである参照型の値があり、関数バーがアクティブになると、ベースがこれに設定されます。
var fooBarReference = {
base: foo,
propertyName: 'bar'
};
ただし、同じ関数が別の方法でアクティブ化された場合、この値は異なります。
var test = foo.bar;
test(); // global
test は識別子として使用されるため、他の参照型の値が生成され、この値のベース (グローバル オブジェクト) が設定されますこの値に。
var testReference = {
base: global,
propertyName: 'test'
};
これで、同じ関数を異なる形式でアクティブ化すると異なる結果が得られる理由を明確に説明できます。その答えは、異なる参照にあります。型の中間値 (型 Reference)。
function foo() {
alert (this) ;
}
foo(); // グローバル、なぜなら
var fooReference = {
base: global,
propertyName: 'foo'
}; alert(foo === foo.prototype.constructor); // true
// 呼び出し式の別の形式
foo.prototype.constructor(); // foo.prototype、
var fooPrototypeConstructorReference = {
base: foo.prototype,
propertyName: 'constructor'
};
次の呼び出しによって this の値を動的に決定する別の古典的な例:
alert(this.bar) );
}
var x = {bar: 10};
x.test = foo; >x.test( ; ただし、他の型の場合、 this の値は自動的に null に設定され、 this の値は実際には暗黙的にグローバル オブジェクトに変換されます。
次の関数式について考えてみましょう:
コードをコピー
コードは次のとおりです:
(function () {
alert(this); // null => グローバル
})();
この例では、関数オブジェクトはありますが、参照型オブジェクトはありません (識別子またはプロパティ アクセサーではないため)。したがって、this の値は最終的にグローバル オブジェクトに設定されます。
より複雑な例:
var foo = {
bar: function () {
alert(this);
foo.bar(); // 参照、OK => (foo .bar)(); // 参照、OK => foo
(foo.bar = foo.bar)(); // グローバル? / global?
(foo.bar, foo.bar)(); // グローバル?
では、なぜ中間値が参照型値である必要があるのでしょうか? 、しかし、一部の呼び出しでは、 this の値がベース オブジェクトではなく、グローバル オブジェクトであることがわかります。
この問題は、次の 3 回の呼び出しで発生します。特定の操作を実行した後、呼び出し括弧の左側の値は参照型ではなくなります。
最初の例は明らかです - 明らかな参照型です。結果として、これが基本オブジェクト、つまり foo になります。
2 番目の例では、グループ化演算子 (翻訳者注: ここでのグループ化演算子は foo.bar の外側の大括弧 "()" を指します) には実際的な意味はありません。参照型を取得するメソッドから上記のことを考えてください。 GetValue などのオブジェクトの実際の値 (11.1.6 を参照)。同様に、グループ化操作の戻り値でも、取得されるのは参照型のままです。これが、this の値がベース オブジェクト (foo) に再度設定される理由です。
3 番目の例では、グループ化演算子とは異なり、代入演算子は GetValue メソッドを呼び出します (11.13.1 の 3 番目のステップを参照)。返された結果はすでに関数オブジェクト (参照型ではない) です。つまり、 this の値は null に設定され、実際の最終結果はグローバル オブジェクトに設定されます。
4 番目と 5 番目は同じです。これに応じて、コンマ演算子と論理演算子 (OR) は GetValue メソッドを呼び出します。そのため、この値は再び に設定されます。グローバルオブジェクト。
参照型であり、これは null
呼び出し式が呼び出し括弧の左側で参照型の値を決定する状況があります。翻訳者注、元のテキストは少し遅れています!)。 、 this の値が null に設定されている限り、最終的には暗黙的にグローバルに変換されます。この状況は、参照型値の基本オブジェクトがアクティブ化オブジェクトである場合に発生します。
次の例では、内部関数が親関数によって呼び出されます。このとき、上記の特殊な状況がわかります。第 2 章で学んだように、ローカル変数、内部関数、および仮パラメータは、特定の関数のアクティベーション オブジェクトに格納されます。
コードをコピー
alert(this); // グローバル
}
bar() // AO.bar() と同じ
}
アクティブ化object は常に this の値として null を返します (つまり、疑似コード AO.bar() は null.bar() と同等です)。 (訳者注: 理解できない場合は、こちらを参照してください) ここで再び上記の状況に戻り、最終的に this の値がグローバル オブジェクトに設定されます。
例外があります: 「関数が with ステートメントで呼び出され、関数名の属性が with オブジェクトに含まれている場合 (訳者注: 以下の例では __withObject)」。 with ステートメントは、そのオブジェクトをスコープ チェーンの先頭、つまりアクティブ化オブジェクトの前に追加します。同様に、参照型は (識別子またはプロパティ アクセサーを通じて) 値を持ち、その基本オブジェクトはアクティブ化オブジェクトではなく、with ステートメントのオブジェクトになります。ちなみに、この状況は内部関数だけでなく、グローバル関数にも関係します。これは、 with オブジェクトがスコープ チェーンの最前面のオブジェクト (グローバル オブジェクトまたはアクティベーション オブジェクト) よりも前にあるためです。
コードをコピーします
alert(this.x);
},
x: 20
}) {
foo(); >}
// because
var fooReference = {
base: __withObject,
propertyName: 'foo'
};
実際のパラメータの関数catch ステートメント 同様の状況が呼び出しにも存在します。この場合、catch オブジェクトはスコープの前、つまりアクティベーション オブジェクトまたはグローバル オブジェクトの前に追加されます。ただし、この特定の動作は ECMA-262-3 のバグであることが確認され、新しいバージョンの ECMA-262-5 で修正されました。修正後、特定のアクティベーション オブジェクト内で、this はグローバル オブジェクトを指します。 catch オブジェクトではなく。
コードをコピー
コードは次のとおりです:
try {
throw function () {
alert(this);
} catch (e) {
e(); ES3、グローバル - ES5 で修正
}
// アイデアに基づいて
var eReference = {
base: __catchObject,
propertyName: 'e'
};ただし、これはバグであるため、
// この値はグローバルに強制されます
// null => global
var eReference = {
base: global,
propertyName: 'e '
};
名前付き関数の再帰呼び出しでも同じ状況が発生します (関数の詳細については、第 5 章「関数」を参照してください)。関数の最初の呼び出しでは、ベース オブジェクトは親アクティブ化オブジェクト (またはグローバル オブジェクト) です。再帰呼び出しでは、ベース オブジェクトは関数式のオプションの名前を格納する特定のオブジェクトである必要があります。ただし、この場合、this の値は常に global に設定されます。
(function foo(bar) { alert( this);
!bar && foo(1) // 特別なオブジェクトである必要がありますが、常に (正しい) global
})(); 🎜>this コンストラクターとして呼び出される関数の値
this の値が関数のコンテキストで関連するもう 1 つの状況は、関数がコンストラクターとして呼び出される場合です。
コードをコピー
コードは次のとおりです。 function A() { alert (this) ; // 新しく作成されたオブジェクト、以下 - "a" オブジェクト this.x = 10>}
var a = new A(); // 10
この例では、新しい演算子は「A」関数内で [[Construct]] メソッドを呼び出し、オブジェクトの作成後にその内部の [[Call]] メソッドを呼び出します。 、すべて同じ関数「A」は両方とも this の値を新しく作成されたオブジェクトに設定します。
関数呼び出しの this を手動で設定する
関数の呼び出し時に this の値を手動で設定できるようにするために、Function.prototype で 2 つのメソッドが定義されています。それらは .apply メソッドと .call メソッドです (すべての関数で使用できます)。アクセスしてください)。彼らは this の値として受け入れる最初の引数を使用します。これは呼び出しスコープで使用されます。 2 つのメソッドに大きな違いはありません。.apply の場合、2 番目のパラメータは配列 (または引数などの配列のようなオブジェクト) である必要があります。これに対して、.call は任意のパラメータを受け入れることができます。両方のメソッドの必須パラメータです。最初の ——this.
alert(this.b) {
alert(c); // this === グローバル, this .b == 10, c == 20
a.call({b: 20}, 30) // this === {b: 20}, this.b == 20, c == 30
a.apply({b: 30}, [40]) // this === {b: 30}, this.b == 30, c == 40
結論
この記事では、ECMAScript におけるこのキーワードの特性について説明します (これらは実際には、対照的に、C や Java の機能です。翻訳者注: この文はあまり役に立ちません。まだわかりません) OK、今は読みません)。この記事が ECMAScript でこのキーワードがどのように機能するかを正確に理解するのに役立つことを願っています。同様に、コメントでの質問に喜んでお答えします。
その他参照 3. 翻訳がどんなに優れていても、原文と一致することはできません。翻訳を読んだ後、原文を注意深く読んでください。