JavaScriptを深く理解するシリーズ(13) そう、これ!_javascriptスキル
はじめに
この記事では、実行コンテキストに直接関連する詳細について説明します。話題になっているのはこのキーワードです。このトピックは難しいことが実際に証明されており、さまざまな実行コンテキストでこれを決定する際に問題が発生することがよくあります。
多くのプログラマは、プログラミング言語において this キーワードはオブジェクト指向プログラム開発と密接に関連しており、コンストラクターによって新しく作成されたオブジェクトを完全に指すものであると信じ込んでいます。これは ECMAScript 仕様にも実装されていますが、後で説明するように、ECMAScript では、これは新しく作成されたオブジェクトを指すことだけに限定されません。
英語翻訳: Dmitry A. Soshnikov、Stoyan Stefanov の協力
発行日: 2010-03-07
http://dmitrysoshnikov.com/ecmascript/chapter-3-this/
ロシア語原文: Dmitry A. Soshnikov
訂正: Zerogif
公開: 2009-06-28;
更新: 2010-03-07
http://dmitrysoshnikov.com/ecmascript /ru-chapter-3-this/
この記事の内容の大部分は、http://www.denisdeng.com/?p=900 を参照しています。
一部の文は、justin の中国語翻訳を参照しています。
コードをコピー
これが ECMAScript で正確に何であるかを詳しく見てみましょう。
定義
これは実行コンテキストの属性です:
activeExecutionContext = {
VO: {...},
this: thisValue
};
ここでの VO は前の章の変数オブジェクトで説明しました。
これはコンテキスト内の実行可能コードのタイプに直接関係しており、この値はコンテキストに入るときに決定され、コンテキストの実行中は変更されません。
これらのケースをさらに詳しく調べてみましょう:
これはグローバル コードです
ここではすべてが簡単です。グローバル コードでは、これは常にグローバル オブジェクト自体であるため、間接的に参照することができます。
// グローバルを定義する属性を表示しますobject
this .a = 10; // global.a = 10
alert(a); // 10
// 識別されない
b = 20; 🎜> alter(this.b); // 20
// グローバル コンテキストの変数オブジェクトはグローバル オブジェクト自体であるため、
// も暗黙的に宣言されます。 = 30;
alert(this.c); // 30
関数コードで this を使用する場合は興味深いですが、この状況は困難であり、たくさんの問題。
このタイプのコードにおけるこの値の最初の (おそらく最も重要な) 特徴は、値が関数に静的にバインドされていないことです。
上で述べたように、これは関数コードに入るときに決定され、この値は毎回まったく異なります。
いずれの場合も、コードの実行中は this の値は変更されません。つまり、変数ではないため、新しい値を割り当てることはできません (対照的に、Python ではプログラミング言語。オブジェクト自体として明確に定義されており、実行時に継続的に変更できます。)
x: 20,
test: function () {
alert(this === bar) // true
alert(this); .x) ; // 20
this = foo; // エラー、this の値はいつでも変更できません
alert(this.x); //エラー。20 ではなく 10 である必要があります。
}
};
// コンテキスト
// これはバー オブジェクトとみなされます
// "bar" オブジェクトとして決定される; その理由 -
// 以下で詳しく説明します
bar.test(); // true、20
foo。 test = bar.test;
// ただし、これは foo ではありません
// 同じ関数が呼び出されますが、
foo.test(); // false 10
したがって、関数コード内のこの値の変更に影響を与える要因がいくつかあります。
まず、通常の関数呼び出しでは、これはコンテキスト コードをアクティブにする呼び出し元によって提供されます。つまり、関数の親コンテキストを呼び出します。これは関数の呼び出し方法によって異なります。
どのような状況でも this の値を正確に判断するには、この重要な点を理解し、覚えておく必要があります。呼び出しのコンテキストで this 値に影響を与えるのは関数の呼び出し方法であり、他には何も影響しません (一部の記事や JavaScript に関する本でさえ、「this 値は関数の定義方法に依存する」と主張されています) 、グローバル関数の場合、これはグローバル オブジェクトに設定されますが、関数がオブジェクトのメソッドの場合、これは常にオブジェクトを指します - これは絶対に当てはまりません)。トピックを続けると、通常のグローバル関数でも、さまざまな形式の呼び出しメソッドによってアクティブ化され、異なる this 値が得られることがわかります。
function foo() {
alert (これ) ;
}
foo(); // グローバル
alert(foo === foo.prototype.constructor) // true
/ / しかし、同じ 関数の呼び出し式が異なる場合、これは異なります
foo.prototype.constructor(); // foo.prototype
は定義されたメソッドとして使用できます一部のオブジェクトによって関数が呼び出されますが、これはこのオブジェクトに設定されません。
var foo = {
bar: function () {
alert(this);
alert(this === foo)
foo.bar();
var exampleFunc = foo.bar;
alert(exampleFunc === foo.bar); // true
// 同じものに対する別の呼び出し式function 、これは異なります
exampleFunc(); // global, false
では、関数の呼び出し方法は this の値にどのように影響するのでしょうか?この値の決定を完全に理解するには、その内部型の 1 つである参照型 (Reference 型) を詳細に分析する必要があります。
参照型 (参照型)
疑似コードを使用すると、参照型の値を 2 つのプロパティを持つオブジェクトとして表すことができます。base (つまり、プロパティを持つオブジェクト) と propertyName の Base です。 。
propertyName:
参照型の値には 2 つの状況しかありません:
またはプロパティ アクセサー
識別子の処理については、次の記事で詳しく説明します。ここで知っておく必要があるのは、このアルゴリズムの戻り値が常に参照型の値であることだけです (これは、これは言うことが重要です)。
識別子は、グローバル オブジェクト内の変数名、関数名、関数パラメータ名、および認識されないプロパティ名です。たとえば、次の識別子の値:
演算の中間結果の参照型に対応する値は次のとおりです:
};
var barReference = {
base: global,
propertyName: 'bar'
};疑似コードで参照型からオブジェクトの実際の値を取得するには GetValue メソッドは次のように記述できます:
if (base === null) {
throw new ReferenceError;
returnbase.[ [Get]](GetPropertyName(value));
}
内部 [[Get]] メソッドは、継承されたプロパティの分析を含む、オブジェクトのプロパティの実際の値を返します。プロトタイプチェーン。
コードをコピー
コードは次のとおりです:
GetValue(fooReference); // 10
GetValue(barReference); // 関数オブジェクト "bar"
属性アクセサーはすべておなじみのはずです。これには、ドット (.) 構文 (プロパティ名が正しい識別子で、事前にわかっている場合) と括弧構文 ([]) の 2 つのバリエーションがあります。
foo.bar(); foo[' bar']();
base: foo,
propertyName: 'bar'
};
GetValue(fooBarReference); // 関数オブジェクト "bar"
関数コンテキストでは、this は呼び出し元によって提供され、関数の呼び出し方法によって決定されます。呼び出し括弧 () の左側が参照型の値である場合、これは参照型値の基本オブジェクトに設定されます。それ以外の場合 (参照型とは異なるその他のプロパティ)、この値は null になります。 。ただし、this の値が null である実際の状況はありません。this の値が null の場合、その値は暗黙的にグローバル オブジェクトに変換されるからです。注: ECMAScript の第 5 版では、グローバル変数への変換は強制されなくなり、未定義に割り当てられます。
この例のパフォーマンスを見てみましょう:
return this;
}
foo(); // グローバル
base: global,
propertyName: 'foo'
};
同様に、プロパティ アクセサーを使用します:
bar: function () {
return this;
}
} // foo
ここでも foo オブジェクトをベースとする参照型があり、これは関数 bar がアクティブ化されたときに使用されます。
コードをコピー
ただし、同じ関数を別の形式でアクティブにすると、他の this 値が取得されます。
コードをコピーします
コードをコピー
これで、異なる形式の式で同じ関数をアクティブ化すると、この値が異なる理由が明確にわかります。さまざまな参照型 (参照型) の中間値。
コードをコピー
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'
};
alert(this.bar)
}
var x = {バー: 10};
var y = {bar: 20};
x.test = foo; // 10
y.test(); // 20
関数呼び出しと非参照型
したがって、前述したように、呼び出し括弧の左側がが参照型ではなく他の型である場合、この値は自動的に null に設定され、結果はグローバル オブジェクトになります。
コードをコピーします
この例では、関数オブジェクト ただし、参照型のオブジェクトではありません (識別子やプロパティ アクセサーではありません)。したがって、 this の値は最終的にグローバル オブジェクトに設定されます。
より複雑な例:
コードをコピーします
(foo.bar)() // 参照、OK => foo
(foo.bar = foo.bar)(); || foo.bar)(); // グローバル?
にプロパティ アクセサがあるのはなぜですか?その途中 値は参照型の値である必要があります。一部の呼び出しでは、取得する this 値はベース オブジェクトではなく、グローバル オブジェクトですか?
問題は、次の 3 つの呼び出しでは、特定の操作を適用した後、呼び出し括弧の左側の値が参照型ではなくなることです。
最初の例は明白です - 明らかな参照型です。その結果、これが基本オブジェクト、つまり foo になります。
2 番目の例では、グループ演算子は適用されません。GetValue など、参照型からオブジェクトの実際の値を取得する上記のメソッドを考えてください。同様に、グループ操作の戻りでも参照型を取得します。これが、 this 値がベース オブジェクト (foo) に再度設定される理由です。
3 番目の例では、グループ演算子とは異なり、代入演算子は GetValue メソッドを呼び出します。返される結果は関数オブジェクト (参照型ではありません) です。つまり、これは null に設定され、結果はグローバル オブジェクトになります。
4 番目と 5 番目も同様です。コンマ演算子と論理演算子 (OR) が GetValue メソッドを呼び出し、それに応じて参照が失われ、関数が取得されます。そして、再度グローバルに設定します。
次のような状況があります。呼び出し側の式が呼び出し括弧の左側で参照型の値を制限している場合、これが null に設定されているにもかかわらず、結果は変換されますグローバルへ。この状況は、参照型値の基本オブジェクトがアクティブ オブジェクトである場合に発生します。
次の例では、内部関数が親関数によって呼び出されます。このとき、上記の特殊な状況がわかります。第 12 章で学んだように、ローカル変数、内部関数、および仮パラメータは、特定の関数のアクティベーション オブジェクトに格納されます。
コードをコピー
コードは次のとおりです。
アクティブなオブジェクトは常に this として返され、値は null です (つまり、疑似コードの AO.bar() は null.bar() と同等です)。ここで、これをグローバル オブジェクトに設定して、上で説明した例に戻ります。
例外が 1 つあります。with オブジェクトに関数名属性が含まれている場合、その関数は with ステートメントの内部ブロックで呼び出されます。 With ステートメントは、オブジェクトのスコープの前、つまりアクティブなオブジェクトの前に追加されます。同様に、(識別子またはプロパティ アクセサーを介した) 参照型があり、その基本オブジェクトはアクティブ オブジェクトではなく、with ステートメントのオブジェクトになります。ちなみに、with オブジェクトはスコープ チェーンの最前面のオブジェクト (グローバル オブジェクトまたはアクティブ オブジェクト) よりも前にあるため、これは内部関数だけでなくグローバル関数にも関連します。
var x = 10; 🎜>with ({
foo: function () {
alert(this.x);
},
x: 20
}) {
foo(); // 20
}
// なぜなら
var fooReference = {
base: __withObject,
propertyName: 'foo '
};
catch ステートメントの関数呼び出しの実際のパラメーターでも同じ状況が発生します。この場合、catch オブジェクトはスコープの前、つまり、アクティブなオブジェクトまたはグローバル オブジェクトのフロント。ただし、この特定の動作は ECMA-262-3 のバグであることが確認されており、ECMA-262-5 の新しいバージョンで修正されています。このようにして、特定のアクティブ オブジェクトで、this はグローバル オブジェクトを指します。 catch オブジェクトではなく。
alert(this);
} catch (e) {
e(); // ES3 標準は __catchObject、ES5 標準はグローバル
}
// アイデアについて
var eReference = {
base: __catchObject,
propertyName: 'e'
}; これは新しいバージョンで修正されました。 ES5 標準 このバグ、
// つまり、これはグローバル オブジェクトです。
var eReference = {
base: global,
propertyName: 'e'
}; 🎜> 名前付き関数の再帰呼び出しでも同じ状況が発生します (関数の詳細については、第 15 章関数を参照してください)。関数の最初の呼び出しでは、ベース オブジェクトは親アクティビティ オブジェクト (またはグローバル オブジェクト) です。再帰呼び出しでは、ベース オブジェクトは関数式のオプションの名前を格納する特定のオブジェクトである必要があります。ただし、この場合、これは常にグローバル オブジェクトを指します。
コードをコピー
コードは次のとおりです。
これは、コンストラクターとして呼び出される関数内です。
この値に関連する別の状況は、関数のコンテキスト、つまりコンストラクターの呼び出しです。
コードをコピー
コードは次のとおりです。
関数呼び出しで this を手動で設定する
関数プロトタイプで定義された 2 つのメソッド (すべての関数がそれにアクセスできるように) を使用すると、関数呼び出しで this 値を手動で設定できます。 .apply メソッドと .call メソッドです。これらは this 値として受け入れる最初の引数を使用し、これは呼び出しスコープで使用されます。これら 2 つのメソッドの違いは非常にわずかです。.apply の場合、2 番目のパラメータは配列 (または引数などの配列のようなオブジェクト) である必要があります。同様に、.call は任意のパラメータを受け入れることができます。両方のメソッドに必要なパラメータは次のとおりです。最初の ——これ。
例:
コードをコピーします
コードは次のとおりです:
var b = 10;

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











同僚は、これによって指摘されたバグのために立ち往生しました。Vue2 のこの指摘の問題により、アロー関数が使用され、その結果、対応する props を取得できなくなりました。私がそれを彼に紹介したとき、彼はそれを知りませんでした。その後、私はわざとフロントエンド コミュニケーション グループに目を向けました。これまでのところ、フロントエンド プログラマーの少なくとも 70% はまだそれを理解していません。今日私はそれを共有しますyou this link. もしすべてが間違っている場合 まだ学習していない場合は、大きな口を与えてください。

1. this キーワード 1. this の型: どのオブジェクトが呼び出されるかがそのオブジェクトの参照型 2. 使用法の概要 1. this.data;//アクセス属性 2. this.func();// アクセスメソッド 3.this ( );//このクラス内の他のコンストラクタを呼び出す 3. 使い方の説明 1.this.dataはメンバメソッドで使用しているので、これを追加しないとどうなるかを見てみましょう classMyDate{publicintyear;publicintmonth;publicintday; publicvoidsetDate(intyear, intmonth,intday){はい

jQuery は、Web 開発における DOM 操作やイベント処理に広く使用されている人気の JavaScript ライブラリです。重要な概念の 1 つは、このキーワードの使用です。 jQuery では、これは現在操作されている DOM 要素を表しますが、コンテキストが異なると、このポインタが異なる場合があります。この記事では、具体的なコード例を通じて、jQuery での this の使用スキルを分析します。まず、簡単な例を見てみましょう。

JavaScript のアロー関数は比較的新しい構文です。独自の this キーワードはありません。逆に、アロー関数の this は、それを含むスコープ オブジェクトを指します。影響は次のとおりです: 1. アロー関数の this は次のとおりです。 static; 2. アロー関数はコンストラクタとして使用できません; 3. アロー関数はメソッドとして使用できません。

これは何ですか?次の記事では、JavaScript でのこれについて説明し、関数の呼び出し方法の違いによる違いについて説明します。

JavaScript はこのポインタをどのように変更するのでしょうか?次の記事では、JS でこのポインターを変更する 3 つの方法を紹介します。

1.this リファレンス 1.1 this リファレンスがあるのはなぜですか? まず、日付クラスの例を書いてみましょう: publicclassclassCode{publicintyear;publicintmonth;publicintday;publicvoidsetDay(inty,intm,intd){year=y;month=m;day= d;}publicvoidprintDate (){System.out.println(年+"-"+月+"-"+日);}publicstatic

この記事は、vue ソース コードを解釈するのに役立ち、これを使用して Vue2 のさまざまなオプションのプロパティにアクセスできる理由を紹介します。
