JavaScriptの詳細な説明 thisキーワード

JavaScriptの詳細な説明 thisキーワード

1. はじめに

this キーワードは、JavaScript で最も複雑なメカニズムの 1 つです。これは、すべての関数のスコープ内で自動的に定義される非常に特殊なキーワードです。このメカニズムを学習する時間を費やしていない JavaScript 開発者にとって、このバインディングは常に非常に混乱を招くものでした。

2.これを理解する

これを学ぶための最初のステップは、これが関数自体や関数の語彙範囲を参照するものではないことを理解することです。このような説明に惑わされているかもしれませんが、実はすべて間違っています。この値は、関数が使用される場所に応じて変化します。しかし、JS の this は常に現在の動作実行の対象を表すという原則があります。JS では、関数内の this が主な研究対象ですが、これは this が関数内にのみ存在することを意味するものではありません。これは実際には関数が呼び出されたときに発生するバインディングです。それが指すものは、関数が呼び出される場所によって完全に異なります。これをどう区別するのでしょうか?

3. これは誰ですか?

これは状況によって異なります。一般的な状況は次の 5 つです。

1. 関数が実行されるとき、まず関数名の前に「.」があるかどうかを確認します。ある場合、「.」の前の人物はこの人物です。ない場合は、これはウィンドウです。

関数fn(){
 console.log(これを);
}
var obj = {fn:fn};
fn();//this->window
obj.fn();//this->obj
関数sum(){
 fn();//this->window
}
和();
var oo = {
 合計:関数(){
 console.log(this);//this->oo
 fn(); //this->window
 }
};
oo.sum();

2. 自己実行関数では、これは常にウィンドウです

(function(){ //this->window })();
 ~function(){ //this->window }();

3. 要素のイベントにメソッドをバインドします。イベントがトリガーされると、対応するメソッドを実行します。メソッド内の this は現在の要素です。ただし、IE6~8 では、attachEvent (IE の有名なバグ) を使用します。

DOM ゼロレベルイベントバインディング

oDiv.onclick=関数(){
 //this->oDiv
 };

DOMセカンダリイベントバインディング

oDiv.addEventListener("クリック",function(){
 //this->oDiv
 }、間違い);

IE6~8でattachEventを使用する場合、デフォルトではウィンドウオブジェクトを参照します。

oDiv.attachEvent("クリック",function(){
 //this->ウィンドウ
 });

ほとんどの場合、次の例のようなイベント バインディングに遭遇します。IE6 ~ 8 の場合、attachEvent の使用についてそれほど真剣に考える必要はありません。

関数fn(){
 console.log(これを);
}
document.getElementById("div1").onclick=fn; //fn 内の this は #div1 です
document.getElementById("div1").onclick=関数(){
console.log(これ);//これ->#div1
fn();//this->window
};

4. コンストラクタモードでは、クラス(関数本体)に現れる this.xxx=xxx 内の this は現在のクラスのインスタンスです。

関数 CreateJsPerson(名前,年齢){
//ブラウザによってデフォルトで作成されるオブジェクトはインスタンス p1->this です
this.name=名前;//->p1.name=名前
this.age=年齢;
this.writeJs = 関数() {
console.log("私の名前は"+this.name +"です。Js を書くことができます");
 };
//ブラウザはデフォルトで作成されたインスタンスを返します}
var p1=new CreateJsPerson("尹华芝",48);

注意すべき点が 1 つあります。クラス内のプロパティ値 (メソッド) の場合、メソッドの実行時にメソッド内の this の前に "." があるかどうかをチェックして、this が誰であるかを知る必要があります。それが何を意味するのかを理解するために、次の例を見てください。

関数Fn(){
this.x = 100; //this->f1
this.getX=関数(){
console.log(this.x); //this->getX がいつ実行されるか確認する必要がある}
}
var f1 = 新しい Fn;
f1.getX(); //-> メソッド内の this は f1 なので、f1.x=100
var ss=f1.getX;
ss(); //->メソッド内のthisはwindow->undefinedです

5.呼び出し、適用、バインド

まず問題を見てみましょう。次の例では、これを obj にどのようにバインドするのでしょうか?

var obj={name:"波間のボート"};
関数fn(){
console.log(this);//this=>window
}
関数fn();
obj.fn(); //->Uncaught TypeError: obj.fn は関数ではありません

obj.fn() を直接バインドすると、プログラムはエラーを報告します。ここでは、このバインディング obj を実装するために fn.call(obj) を使用する必要があります。次に、call メソッドを詳しく紹介します。

call メソッドの機能:

①まずプロトタイプに対してcallメソッドを実行します。callメソッド実行時にfnメソッド内のthisを第一引数値objに変更し、fn関数を実行します。

②呼び出しは値を渡すこともできます。StrictモードとNon-Strictモードでは取得できる値が異なります。

//非厳密モードの場合 var obj={name:"浪里行舟"};
関数 fn(num1,num2){
コンソールログ(数値1+数値2);
console.log(これを);
}
fn.call(100,200);//this->100 num1=200 num2=未定義
fn.call(obj,100,200);//this->obj num1=100 num2=200
fn.call();//this->window
fn.call(null);//this->window
fn.call(undefined);//this->window
// 厳密モードではfn.call(); // 厳密モードではthis->undefined
fn.call(null); // 厳密モードでは this->null
fn.call(undefined); // 厳密モードでは this->undefined

**applyメソッドとcallメソッドの機能はまったく同じで、どちらもメソッドのthisキーワードを変更するために使用されます。

実行され、厳密モードと非厳密モードで最初のパラメータが null/undefined の場合のルール

法律についても同様です。 **

両者の唯一の違いは、call はパラメータを 1 つずつ fn に渡すのに対し、apply はパラメータを 1 つずつ渡すのではなく、fn に渡すパラメータ値を配列に入れて操作するという点です。しかし、これは fn のパラメータに値を 1 つずつ割り当てることと同等です。 まとめると、callの2番目のパラメータはパラメータリストを受け入れるようになり、applyの2番目のパラメータはパラメータ配列を受け入れるようになる。

呼び出し元オブジェクトを 100,200 に設定します。
fn.apply(obj,[100,200]);

bind: このメソッドは IE6-8 と互換性がありません。 this キーワードを変更するために使用されるという点で call/apply に似ていますが、次の 2 つとは大きく異なります。
fn.call(obj,1,2); //->これを変更してfn関数を実行すると、同時に実行されます

fn.bind(obj,1,2);//-> fn 内の this を obj に変更し、2 つのパラメータ値 1 と 2 を fn に渡します。
 しかし、この時点では fn 関数は実行されません var tempFn=fn.bind(obj,1,2);
tempFn(); //fn関数はこのように実行されます

Bind は前処理の考え方を具体化します。つまり、fn の this を事前に必要な結果に変更し、対応するパラメータ値も準備して、将来必要になったときに直接実行できるようにします。

呼び出しと適用は関数を直接実行しますが、bind では別の呼び出しが必要になります。

var a = {
 名前:「チェリー」
 fn:関数(a,b){
 コンソールログ(a + b)
 }
 }
 var b = a.fn;
 b.bind(a,1,2)

上記のコードは実行されません。Bind はコンテキストを変更する関数を返します。これを手動で呼び出す必要があります。

b.bind(a,1,2)() //3

1 つだけ述べておくべきことがあります。5 番目の状況 (apply と bind の呼び出し) に遭遇すると、最初の 4 つの状況はすべて無視されます。

4.矢印関数は

矢印関数は、その名前が示すように「矢印」(=>)を使用して関数を定義する新しい構文ですが、従来の関数よりも短く、バインドされないという 2 つの点で優れています。

var obj = {
 生年月日: 1990年
 getAge: 関数 () {
 var b = this.birth; // 1990
 var fn = 関数() {
 return new Date().getFullYear() - this.birth; // this は window または undefined を参照します
 };
 fn() を返します。
 }
};

これで、矢印関数は this の方向を完全に固定します。矢印関数には独自の this はありません。矢印関数の this は呼び出されたときに決定されるのではなく、それが定義されているオブジェクトがその this になります。

つまり、矢印関数の this は、外側のレイヤーに関数があるかどうかによって決まります。外側のレイヤーに関数がある場合、外側の関数の this は内側の矢印関数の this になります。外側のレイヤーに関数がない場合、this はウィンドウになります。

<button id="btn1">矢印関数 this_1 をテストする</button>
 <button id="btn2">矢印関数 this_2 をテストする</button>
 <script type="text/javascript"> 
 btn1 = document.getElementById('btn1'); とします。
 obj = {
 名前: 'kobe',
 年齢: 39歳
 getName: 関数 () {
 btn1.onclick = () => {
 console.log(これ);//obj
 };
 }
 };
 オブジェクト名を取得します。
 </スクリプト>

上記の例では、矢印関数は独自の this を作成しないため、スコープ チェーンの前のレベルから this を継承するだけです。実際、次のコードに簡略化できます。

btn1 = document.getElementById('btn1'); とします。
 obj = {
 名前: 'kobe',
 年齢: 39歳
 getName: 関数 () {
 console.log(これ)
 }
 };
 オブジェクト名を取得します。

前のレイヤーに関数がない場合、これは誰を指すのでしょうか?

<button id="btn1">矢印関数 this_1 をテストする</button>
 <button id="btn2">矢印関数 this_2 をテストする</button>
 <script type="text/javascript"> 
 btn2 = document.getElementById('btn2'); とします。
 obj = {
 名前: 'kobe',
 年齢: 39歳
 取得名: () => {
 btn2.onclick = () => {
 console.log(this);//ウィンドウ
 };
 }
 };
 オブジェクト名を取得します。
 </スクリプト>

上記の例では、矢印関数が 2 つありますが、これは実際には最も外側の矢印関数に依存します。obj は関数ではなくオブジェクトであるため、これは Window オブジェクトを指します。

これは、字句スコープに従って矢印関数にバインドされるため、call() または apply() を使用して矢印関数を呼び出すときにはバインドできません。つまり、渡される最初のパラメーターは無視されます。

var obj = {
 生年月日: 1990年
 getAge: 関数 (年) {
 var b = this.birth; // 1990
 var fn = (y) => y - this.birth; // this.birth はまだ 1990 年です
 fn.call({birth:2000}, year); を返します。
 }
};
obj.getAge(2018); // 28

さらに読む

矢印機能 - 廖雪峰

JS の矢印関数と this

これを適用し、呼び出す、バインドする

要約する

JavaScript thisキーワードの詳細な説明はこれで終わりです。JavaScript thisキーワードの関連コンテンツについては、123WORDPRESS.COMの過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

以下もご興味があるかもしれません:
  • js の this キーワードの詳細な説明
  • js の this キーワードの理解
  • Javascriptのこのキーワードの使用状況の分析
  • js thisキーワードに関する質問
  • JavaScriptのthisキーワードをマスターする
  • JavaScript の this キーワードの図解説明
  • JavaScript で this キーワードを使用する方法の詳細な説明
  • JavaScriptのthisキーワードの詳しい説明
  • JavaScript で this キーワードを使用する方法の概要
  • このキーワードのJavaScriptでの詳細な説明

<<:  Vueはマルチタブコンポーネントを実装します

>>:  JS での矢印関数と this の記述と理解

推薦する

バックアップ データをインポートするときに innodb_index_stats がエラーを報告する場合の主キー競合の解決方法

障害の説明percona5.6、mysqldump フルバックアップ、バックアップデータのインポート...

nginx のフロントエンドとバックエンドに同じドメイン名を設定する方法

この記事では、主にnginxのフロントエンドとバックエンドに同じドメイン名を設定する方法を紹介し、皆...

JavaScript カウントダウン プロンプト ボックス

この記事の例では、カウントダウンプロンプトボックスを実装するためのJavaScriptの具体的なコー...

CSSテーマを簡単に切り替える方法の詳細な説明

最近、個人の Web サイトに非常にシンプルなカラー スキーム (テーマ) スイッチャーを追加しまし...

Vue ベースの円形スクロールリスト機能を実装する

注: 親コンテナーに高さと :data='Array' および overfolw:h...

ReactのEffectListの簡単な分析

目次EffectList コレクション最初のレンダリング時のEffectList EffectLis...

Linux でディスク IO を表示し、読み取りと書き込みで高い IO を占有するプロセスを見つけます。

背景 - オンラインアラートオンライン サーバーがアラームを発し、ディスク使用率 disk.util...

CSS3を使用してトランジションとアニメーション効果を実現する

JS アニメーションの代わりに CSS アニメーションを使用する必要があるのはなぜですか? Java...

DockerはRedis5.0をビルドし、データをマウントします

目次1. 永続データの簡単なマウント2. DockerFileでイメージをビルドし、設定ファイルを指...

Angularが予期しない例外エラーを処理する方法の詳細な説明

前面に書かれたコードがどれだけ適切に記述されていても、すべての可能性のある例外を完全に処理することは...

Vue プロジェクトをパッケージ化して Apache サーバーにデプロイする手順

開発環境では、vue プロジェクトは、ローカルで Express サーバーを構築することをベースにし...

Vueのドラッグスクリーンショット機能を実装する簡単な方法

マウスをドラッグしてページのスクリーンショットを撮ります(指定した領域にスクリーンショットをドラッグ...

JQueryセレクターの詳細な説明

目次基本的なセレクター:レベルセレクター:属性セレクター:フィルターセレクター:フォーム属性セレクタ...

Vueは透かし効果を簡単に実現します

序文: Vueプロジェクトで透かし効果を使用するには、コンテナを指定できます効果画像: 1. コンテ...

Docker が PostgreSQL を起動するときに複数のデータベースを作成するためのソリューション

1 はじめに「DockerでPostgreSQLを起動する方法といくつかの接続ツールのおすすめ」の記...