矢印関数」と「関数」は等価交換可能か

javascript ecmascript-6 arrow-functions


ES2015の矢印関数は、より簡潔な構文を提供します。

  • 私の関数宣言式をすべて矢印関数に置き換えることはもうできますか?
  • 何に気をつければいいの?

Examples:

コンストラクタ関数

function User(name) {
  this.name = name;
}

// vs

const User = name => {
  this.name = name;
};

試作法

User.prototype.getName = function() {
  return this.name;
};

// vs

User.prototype.getName = () => this.name;

オブジェクト (リテラル)メソッド

const obj = {
  getName: function() {
    // ...
  }
};

// vs

const obj = {
  getName: () => {
    // ...
  }
};

Callbacks

setTimeout(function() {
  // ...
}, 500);

// vs

setTimeout(() => {
  // ...
}, 500);

バラエティ機能

function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// vs
const sum = (...args) => {
  // ...
};



Answer 1 Felix Kling


tl; dr:いいえ!アロー関数と関数宣言/式は同等ではなく、盲目的に置き換えることはできません。
交換したい機能がない場合ではない使用 thisarguments とで呼び出されていない new [はい、。


頻繁に:それは依存します。アロー関数は関数宣言/式とは異なる動作をするので、最初に違いを見てみましょう:

1.字句の thisarguments

アロー関数には、独自の this または arguments バインディングはありません。代わりに、これらの識別子は他の変数と同様に字句スコープで解決されます。つまり、矢印関数の内部では、 thisarguments は、矢印関数が定義されている環境(つまり、矢印関数の「外部」)で thisarguments 値を参照します。

// Example using a function expression
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

関数式の場合、 thiscreateObject 内で作成されたオブジェクトを参照します。アロー関数の場合、 thiscreateObject 自体の this を指します。

これにより、現在の this 環境にアクセスする必要がある場合に、矢印関数が役立ちます。

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

これは、アロー関数の this.bind または .call で設定できないことも意味することに注意しください

あなたは非常に精通していない場合 this 、読んでみてください

2.アロー関数は new で呼び出すことはできません

ある関数間ES2015区別呼んでいることや機能の構築が可能。関数が構築可能な場合、 new 、つまり new User() で呼び出すことができます 。関数が呼び出し可能である場合、 new 関数なしで呼び出すことができます(つまり、通常の関数呼び出し)。

関数宣言式で作成された関数は、構築可能なものと呼び出し可能なものの両方があります。
矢印関数(およびメソッド)は呼び出しのみ可能です。 class コンストラクターは構築のみ可能です。

呼び出し不可能な関数を呼び出そうとしたり、構造化不可能な関数を構築しようとすると、実行時エラーが発生します。


これを知っていると、次のように述べることができます。

Replaceable:

  • this または arguments 使用しない関数。
  • .bind(this) で使用される関数

交換不可

  • コンストラクタ関数
  • プロトタイプに追加された関数/メソッド(通常、 this 使用するため)
  • 可変個の関数(引数を使用する arguments (下記参照))

あなたの例を使って、これを詳しく見てみましょう。

コンストラクター関数

アロー関数は new で呼び出すことができないため、これは機能しません。関数宣言/式を使い続けるか、 class を使用してください。

プロトタイプの方法

プロトタイプメソッドは通常、 this を使用してインスタンスにアクセスするため、おそらくそうではありません。彼らが使用していない場合は this 、その後、あなたはそれを置き換えることができます。ただし、主に簡潔な構文を重視する場合は、簡潔なメソッド構文で class を使用します。

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

オブジェクトのメソッド

オブジェクトリテラルのメソッドについても同様です。メソッドが this を介してオブジェクト自体を参照する場合は、関数式を引き続き使用するか、新しいメソッド構文を使用します。

const obj = {
  getName() {
    // ...
  },
};

Callbacks

場合によります。外側の this にエイリアスを .bind(this) 場合、または.bind(this)を使用している場合は、必ず置き換えてください。

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

しかし:コールバックを呼び出すコードが this を明示的に特定の値に設定する場合、特にjQueryのイベントハンドラーでよくあることであり、コールバックが this (または arguments )を使用する場合、矢印関数使用できません

可変関数

アロー関数には独自の arguments がないため、単純にアロー関数に置き換えることはできません。ただし、ES2015では、 arguments を使用する代わりに、残りのパラメーターを導入しています。

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};

関連する質問です。

その他のリソース。




Answer 2 Ashutosh


矢印関数=>これまでのところ最高のES6機能。これらは、私が常に使用している、ES6への非常に強力な追加機能です。

待ってください、あなたはコードのどこでもアロー関数を使うことができません、それはアロー関数が使用できない this ようなすべてのケースで機能することはないでしょう。間違いなく、arrow関数はコードを単純化する優れた機能です。

ただし、動的コンテキストが必要な場合は、矢印関数を使用できません。メソッドの定義、コンストラクターを使用したオブジェクトの作成、イベントの処理時にこれからターゲットを取得します。

矢印関数は使用すべきではないからです。

  1. 彼らは持っていません。 this

    「レキシカルスコーピング」を使用して、「 this 」の値を理解します。簡単な単語のレキシカルスコープでは、関数の本体の内部から「 this 」を使用します。

  2. 彼らは arguments 持っていません

    矢印関数には arguments オブジェクトはありません。ただし、残りのパラメーターを使用して同じ機能を実現できます。

    let sum = (...args) => args.reduce((x, y) => x + y, 0) sum(3, 3, 1) // output - 7 3、3、1 )//出力-7 `

  3. new では使用できません

    矢印関数はプロトタイプのプロパティを持っていないので、コンストラクタにはなりません。

矢印機能を使うタイミングと使わないタイミング

  1. アクセスできないので、オブジェクトリテラルのプロパティとして関数を追加するのはやめましょう。
  2. 関数式はオブジェクトメソッドに最適です。矢印関数は、 mapreduceforEach などのコールバックまたはメソッドに最適です。
  3. 名前で呼び出す関数には関数宣言を使用します(関数は巻き上げられるため)。
  4. コールバックには矢印関数を使用してください (これは、より速くなる傾向があるからです)。