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 の記述と理解

推薦する

MySQL シリーズ 14 MySQL 高可用性実装

1. 内閣府マスターノードを監視することで、他のスレーブノードへの自動フェイルオーバーを実現できます...

PSを使用して2分でxhtml+cssウェブサイトのホームページを作成します

xhtml+css のウェブサイト再構築、ウェブ標準などについては、記事が多すぎるので繰り返しません...

CSS で透明なグラデーション効果を実装するためのサンプルコード

Zhihu Discovery コラムのタイトル画像は、通常、以下のように表示されます。明らかに、グ...

MySQL初心者のための基本操作のまとめ

図書館運営クエリ1.SHOW DATABASE; ----すべてのデータベースを照会する2. SHO...

JavaScript の基本: ループと配列

目次ループ - for forループの基本的な使い方ループを終了するネストされたループ配列配列とは何...

iframe なしの div ネスト HTML

最近、宿題をしているときに、iframe を使用せずにページをネストする必要があったため、jquer...

Linux 7.7 でスワップ パーティション SWAP を設定する方法

Linux システムの Swap パーティション、つまり swap パーティションは、一般に仮想メモ...

MySQL 基本チュートリアル パート 1 MySQL5.7.18 のインストールと接続チュートリアル

この記事から、MySQL を紹介し学習するための新しい一連の記事がスタートします。なぜ MySQL ...

サブメニューをクリックする効果を実現するJavaScript

この記事では、クリック時にサブメニューを表示するためのJavaScriptの具体的なコードを参考まで...

uniappがインターフェースドメイン名を動的に取得する方法を分析する

背景インターフェイス ドメイン名はハードコードされておらず、動的に取得されます。具体的な実装は、静的...

Vue で PC アドレスをモバイル アドレスにリダイレクトする方法

要件:PC側とモバイル側は2つの独立したプロジェクトです。2つのプロジェクトの内容は基本的に同じで、...

Vueは複数列レイアウトドラッグを実装します

この記事では、マルチカラムレイアウトドラッグを実装するためのVueの具体的なコードを参考までに共有し...

MySQL サブクエリとグループ化されたクエリ

目次概要サブクエリサブクエリの分類クエリの結果によるとサブクエリの位置で区別する選択後のサブクエリサ...

HTML でフォーム入力やその他のテキスト ボックスを読み取り専用にして編集不可にする方法

場合によっては、フォーム内のテキスト ボックスを読み取り専用にして、ユーザーがその中の情報を変更でき...

Vue3ライフサイクル関数とメソッドの詳細な説明

1. 概要いわゆるライフサイクル機能とは、特定の条件下で自動的にトリガーされる機能です。 2. VU...