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

推薦する

入力選択スタイルを変更する CSS 疑似クラスのサンプルコード

注: この表はW3Schoolチュートリアルから引用したものです疑似要素の分類と機能: 入力選択スタ...

ノードを使用して静的ファイルキャッシュを実装する方法

目次キャッシュキャッシュ位置の分類キャッシュ設定ヘッダーNodeは静的ファイルキャッシュを実装する強...

HTML のキャンバスに基づくスクリーンショットのデモ

冒頭に書いた以前、Renren で JS ベースのスクリーンショット ソリューションについて説明した...

Vueはシンプルなショッピングカートの例を実装します

この記事では、Vueの具体的なコードを共有して、簡単なショッピングカートを実装します。具体的な内容は...

JavaScript 中断要求に対するいくつかの解決策の詳細な説明

目次1 約束呼び出しチェーンを中断する約束を破る中止メソッドのラッピング - Axios の Can...

Vue要素と多言語切り替えの詳細な説明

目次序文複数の言語を切り替えるにはどうすればいいですか? 1. vue-i18nパッケージをインスト...

MySQLのダウンロードとインストールのプロセスの詳細な説明

1: MySqlをダウンロードする公式サイトのダウンロードアドレス: https://dev.mys...

CSS の position 属性の値に関する研究 (概要)

CSS の位​​置属性は要素の配置タイプを指定し、上、下、左、右を使用して要素を具体的に配置します...

MySQLデータベース監視binlogを有効にする手順

序文多くの場合、ユーザーが自分のデータに対して実行する操作に基づいて何かを行う必要があります。たとえ...

Raspberry PiにDockerをインストールする方法

Raspberry Pi は ARM アーキテクチャをベースとしているため、Docker のインスト...

Centos7 での MySQL 5.7.20 のインストールと設定に関する詳細なチュートリアル

1. 公式 Web サイトから MySQL 5.7 インストール パッケージ (mysql-5.7....

Vue画像拡大鏡コンポーネントのカプセル化と使用方法の詳細な説明

Vue画像拡大鏡コンポーネントパッケージに基づいて、参考までに具体的な内容は次のとおりです。画像拡大...

jsはショッピングサイトの虫眼鏡機能を実現します

この記事では、ショッピングサイトの虫眼鏡機能を実現するためのjsの具体的なコードを紹介します。具体的...

Vueはページの部分的なリフレッシュを実装します(ルータビューのページリフレッシュ)

Vue でprovide+inject組み合わせを使用するまず、App.vue を変更する必要があ...

JavaScript のコールバック関数の理解と使用

目次概要コールバックまたは高階関数とは何ですか?コールバック関数はどのように機能しますか?コールバッ...