この記事では、特定の極端なケースをより良く理解するための高度なトピックを取り扱います。
これは重要ではありません。多くの経験豊富な開発者は、これを知らなくても問題なく生活できます。内部でどのように動作するかを知りたい場合は、読み進めてください。
動的に評価されたメソッド呼び出しは、this
を失う可能性があります。
例えば
let user = {
name: "John",
hi() { alert(this.name); },
bye() { alert("Bye"); }
};
user.hi(); // works
// now let's call user.hi or user.bye depending on the name
(user.name == "John" ? user.hi : user.bye)(); // Error!
最後の行には、user.hi
または user.bye
のいずれかを選択する条件演算子があります。この場合、結果は user.hi
です。
次に、メソッドはすぐに括弧 ()
で呼び出されます。しかし、これは正しく機能しません!
ご覧のとおり、呼び出しはエラーになります。これは、呼び出し内の "this"
の値が undefined
になるためです。
これは機能します(オブジェクトのドットメソッド)
user.hi();
これは機能しません(評価されたメソッド)
(user.name == "John" ? user.hi : user.bye)(); // Error!
なぜ?なぜそうなるのかを理解したい場合は、obj.method()
の呼び出しがどのように機能するかを詳しく見てみましょう。
参照型の説明
よく見ると、obj.method()
ステートメントには2つの操作があることに気付くでしょう。
- 最初に、ドット
'.'
がプロパティobj.method
を取得します。 - 次に、括弧
()
がそれを実行します。
では、this
に関する情報は、最初の部分から2番目の部分にどのように渡されるのでしょうか?
これらの操作を別々の行に記述すると、this
は確実に失われます。
let user = {
name: "John",
hi() { alert(this.name); }
};
// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
ここで、hi = user.hi
は関数を変数に入れ、最後の行では完全にスタンドアロンであるため、this
はありません。
user.hi()
の呼び出しを機能させるために、JavaScript はトリックを使用します。ドット '.'
は関数ではなく、特別な 参照型 の値を返します。
参照型は「仕様型」です。これを明示的に使用することはできませんが、言語内部で使用されます。
参照型の値は、3つの値の組み合わせ (base, name, strict)
です。ここで
base
はオブジェクトです。name
はプロパティ名です。strict
は、use strict
が有効な場合は true です。
プロパティアクセス user.hi
の結果は関数ではなく、参照型の値です。厳格モードでの user.hi
の場合は次のようになります。
// Reference Type value
(user, "hi", true)
参照型で括弧 ()
が呼び出されると、オブジェクトとそのメソッドに関する完全な情報が提供され、正しい this
(この場合は user
)を設定できます。
参照型は、ドット .
から呼び出し括弧 ()
に情報を渡すことを目的とした特別な「仲介」内部型です。
代入 hi = user.hi
のような他の操作は、参照型全体を破棄し、user.hi
(関数)の値を取得して渡します。したがって、それ以降の操作は this
を「失い」ます。
したがって、結果として、this
の値は、ドット obj.method()
または角括弧 obj['method']()
構文(ここでは同じことをします)を使用して関数を直接呼び出す場合にのみ、正しく渡されます。この問題を解決するには、func.bind() など、さまざまな方法があります。
概要
参照型は言語の内部型です。
obj.method()
のドット .
のようにプロパティを読み取ると、プロパティ値そのものではなく、プロパティ値とそれが取得されたオブジェクトの両方を格納する特別な「参照型」の値が返されます。
これは、後続のメソッド呼び出し ()
がオブジェクトを取得し、this
をそれに設定するためです。
他のすべての操作では、参照型は自動的にプロパティ値(この場合は関数)になります。
全体のメカニズムは私たちの目には隠されています。メソッドが式を使用してオブジェクトから動的に取得される場合など、微妙な場合にのみ問題になります。
コメント
<code>
タグを使用し、数行の場合は<pre>
タグで囲み、10行を超える場合はサンドボックスを使用してください(plnkr, jsbin, codepen…)