ES6の通常関数とアロー関数の違い

アロー関数と通常の関数の違い

ES6で新たに追加されたアロー関数の構文として開発者に深く愛されており、フロントエンドのインタビューでもよく聞かれる典型的な質問でもあります。コードを簡素化するだけでなく、開発者がこの点での「不安定な」点を取り除くこともできます。この記事では、アロー関数と通常の関数の違いを分析します。

私の意見では、インタビュアーが最も懸念していること、そして 2 つの間の最も重要な違いは、このポインティングの違いです。通常の関数では、これは関数が呼び出されるオブジェクトをポイントするため、異なる呼び出し元では、このポインティングの値が異なります。異なります。アロー関数には独自の this がありません (同時に、アロー関数には this、argument、super などの他のローカル変数もありません)。そのため、アロー関数の this は固定されており、関数が定義されているオブジェクトを指します。

一般関数
一般関数の使い方は皆さんもよくご存じかと思いますが、以下に簡単な例を挙げてみましょう。

var a  = 3;
var obj = {
    
    
    a : 1,
    foo : function(){
    
    
        console.log(this.a);
    }
}
obj.foo(); //1
var bar = obj;
bar.a = 2;
bar.foo(); //2
var baz = obj.foo;
baz(); //3

上記のコードには、次の 3 つの状況があります。

obj を介してメソッド foo を直接呼び出します。このとき、これは foo 関数を呼び出すオブジェクト、つまり obj を指します。obj オブジェクトを
新しいオブジェクト bar に割り当てます。このとき、bar を介して foo 関数を呼び出します。この値は、呼び出し元 bar を指します
。obj.foo を新しいオブジェクト baz に割り当て、baz() を通じて foo 関数を呼び出します。この時点では、これは window を指します。
ここから、次の結論を導き出すことができます。

通常の関数の this は、常にその直接の呼び出し元を参照します。
厳密モードでは、直接の呼び出し元が見つからない場合、関数内のこれは未定義です。
デフォルト モード (非厳密モード) では、直接の呼び出し元が見つからない場合、関数内の this は window を指します。
もう一度次の状況を考えてみましょう。

var obj = {
    
    
    a : 1,
    foo : function(){
    
    
        setTimeout(
            function(){
    
    console.log(this.a),3000})
    }
}
obj.foo(); //undefined

この時点で出力は 1 になるはずだと思うかもしれませんが、結果は未定義です。現時点では、これはグローバル ウィンドウ オブジェクトを指しているためです。
上記の例から、次の結論が導き出されます。

メソッド (つまり、関数がオブジェクトを通じて呼び出される) の場合、通常の関数の this は常に呼び出し元を指します。
一般的な関数の場合、これはグローバル変数 (非厳密モードの場合) または未定義 (厳密モードの場合) を指します。上記の例では、setTimeout の関数はどのオブジェクトからも呼び出されないため、この時点はまだ window オブジェクトのままです。したがって、これをまとめると次のようになります: JavaScript のこれは単純に遅延バインディングと考えることができ、バインドする場所がない場合、デフォルトではウィンドウまたは未定義にバインドされます。
上記の例の setTimeout 関数でこれを使用できるようにしたい場合はどうすればよいでしょうか? アロー関数が登場する前は、次の 2 つの方法を使用する傾向がありました。

setTimeout 関数の外側、つまり上位レベルの関数 foo の内側では、これは this の値を一時変数に代入することで実現されます。

var obj = {
    
    
    a : 1,
    foo : function(){
    
    
        var that  = this;
        setTimeout(
            function(){
    
    console.log(that.a),3000})
    }
}
obj.foo(); //1

これをbind()でバインドします。

var obj = {
    
    
    a : 1,
    foo : function(){
    
    
        setTimeout(
            function(){
    
    console.log(this.a),3000}.bind(this))
    }
}
obj.foo(); //1

この現象はES6でアロー機能が導入されて改善されました。

アロー関数
アロー関数は ES6 で導入された新機能で、使用方法は次のとおりです。

()=>{
    
    console.log(this)}

() は取り込まれるパラメータ、{} は実行されるステートメントです。アロー関数は、関数型プログラミングの一種です。関数型プログラミングは、プロセスのいくつかの要素を省略して、入力と出力の関係に重点を置いています。したがって、アロー関数には、独自の this、引数、新しいターゲット (ES6) および super(ES6) がありません。 )。アロー関数は匿名関数と同等であるため、new をコンストラクターとして使用することはできません。
アロー関数内の this は、常に親スコープ内の this を指します。言い換えれば、アロー関数は、コンテキストの this 値を独自の this 値として取得します。call()、bind()、apply() などのメソッドはポイントを変更できません。this がアロー関数で呼び出されると、単にスコープ チェーンを検索し、使用する最も近い this を見つけます。これは呼び出しのコンテキストとは何の関係もありません。コードで説明してみましょう。

var obj = {
    
    
    a: 10,
    b: () => {
    
    
      console.log(this.a); // undefined
      console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    },
    c: function() {
    
    
      console.log(this.a); // 10
      console.log(this); // {a: 10, b: ƒ, c: ƒ}
    },
    d:function(){
    
    
        return ()=>{
    
    
            console.log(this.a); // 10
        }
    },
    e:function(){
    
    
      setTime
    }
  }
  obj.b(); 
  obj.c();
  obj.d()();

コードを分析するだけで、obj.b() の this は親コンテキストの this 値を継承します。つまり、グローバル変数ウィンドウである obj と同じ this ポインターを持ちます。obj.c() の this ポイントは呼び出し元 obj であり、obj.d().() の this も親コンテキストの this ポイント、つまり d の this ポイント (obj) を継承します。

この例を通じて、通常の関数の this と匿名関数の this の違いを大まかに理解することができ、業務上の必要に応じてこれら 2 つの関数を正しく合理的に使用できるようになります。

おすすめ

転載: blog.csdn.net/m1009113872/article/details/110004615