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.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をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
目次マルチ環境構成とは何ですか? また、なぜそれが必要なのですか? .env ファイルはどこで設定さ...
1. インストールapt-get install mysql-server にはアカウントとパスワー...
Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....
1. nginxソースディレクトリに新しいrtmpディレクトリを作成し、git clone http...
目次vueカスタムディレクティブグローバル指令ローカル指示使用フック関数(両方ともオプション)使用方...
最近、社内の重要なサーバデータを定期的にストレージにバックアップし、ついでにメモしておきたい以前、W...
この記事の例では、ドラッグアンドドロップを使用して構造ツリーを作成するVueの具体的なコードを共有し...
方法:説明: どちらも達成できません:方法1: sp_product から sp.productid...
JavaScript スクリプトは HTML 内のどこにでも埋め込むことができますが、いつ呼び出され...
1. CSSスタイルは、テキストが長すぎる場合に省略記号を表示する問題を解決します1. 一般的なスタ...
注: sg11 弊社では Linux システム仮想ホストのセルフインストールのみサポートしております...
インターネットは絶えず進化する有機体です。長期にわたってインターネットの発展に適応できるページを構築...
目次情事の概念取引の状態取引の役割取引の特徴トランザクション構文トランザクション対応ストレージエンジ...
クエリキャッシュ制限query_cache_limit は、単一のクエリで使用できるバッファ サイズ...
antd-mobileをインストールするグローバル輸入 npm をインストール antd-mobil...