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

推薦する

vueプロジェクトのマルチ環境設定(.env)の実装

目次マルチ環境構成とは何ですか? また、なぜそれが必要なのですか? .env ファイルはどこで設定さ...

MySQLをインストールして設定し、ルートパスワードを変更する方法

1. インストールapt-get install mysql-server にはアカウントとパスワー...

Nginx Rewrite の使用シナリオと設定方法の分析

Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....

Nginx は rtmp ライブ サーバーの実装コードを構築します

1. nginxソースディレクトリに新しいrtmpディレクトリを作成し、git clone http...

Vueのフィルターとディレクティブの詳細な説明

目次vueカスタムディレクティブグローバル指令ローカル指示使用フック関数(両方ともオプション)使用方...

Centos7 での Rsync+crontab 定期同期バックアップ

最近、社内の重要なサーバデータを定期的にストレージにバックアップし、ついでにメモしておきたい以前、W...

Vueはドラッグアンドドロップを使用して構造ツリーを作成します

この記事の例では、ドラッグアンドドロップを使用して構造ツリーを作成するVueの具体的なコードを共有し...

MySQLで行または列をソートする方法

方法:説明: どちらも達成できません:方法1: sp_product から sp.productid...

JavaScript スクリプトが実行されるタイミングの詳細な説明

JavaScript スクリプトは HTML 内のどこにでも埋め込むことができますが、いつ呼び出され...

CSSスタイルは、テキストが長すぎる場合に省略記号を表示する問題を解決します

1. CSSスタイルは、テキストが長すぎる場合に省略記号を表示する問題を解決します1. 一般的なスタ...

Linux 仮想ホストで SourceGuardian (sg11) 暗号化コンポーネントを有効にする詳細な手順

注: sg11 弊社では Linux システム仮想ホストのセルフインストールのみサポートしております...

きちんとしたHTMLマークアップを使用してページを構築します

インターネットは絶えず進化する有機体です。長期にわたってインターネットの発展に適応できるページを構築...

MySQL トランザクションの概念と使用法の詳細な説明

目次情事の概念取引の状態取引の役割取引の特徴トランザクション構文トランザクション対応ストレージエンジ...

MySQL 最適化 query_cache_limit パラメータの説明

クエリキャッシュ制限query_cache_limit は、単一のクエリで使用できるバッファ サイズ...

React はモバイル端末を構築するために antd-mobile+postcss を導入しました

antd-mobileをインストールするグローバル輸入 npm をインストール antd-mobil...