web-dev-qa-db-ja.com

「矢印機能」と「機能」は同等/交換可能ですか?

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

  • すべての関数宣言/式を矢印関数に置き換えられますか?
  • 私は何を注意しなければなりませんか?

例:

コンストラクタ関数

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: () => {
    // ...
  }
};

コールバック

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

// vs

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

可変関数

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

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

tl; dr:No!矢印関数と関数宣言/式は同等ではなく、盲目的に交換することはできません。
置き換えたい関数がnotを使用しない場合(---)thisargumentsを使用し、newで呼び出されない場合、はい。


頻繁に:it depend。矢印関数の動作は関数の宣言/式とは異なるため、まず違いを見てみましょう。

1。字句thisおよびarguments

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

// 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内に作成されたオブジェクトを指します。矢印関数の場合、thisthis of createObject自体を指します。

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

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

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

これは、矢印関数のthisを設定することはnot.bindまたは.call

thisにあまり詳しくない場合は、読むことを検討してください

2。矢印関数はnewで呼び出すことはできません

ES2015は、callable関数とconstructable関数を区別します。関数が構築可能な場合、new、つまりnew User()で呼び出すことができます。関数が呼び出し可能な場合、newなしで呼び出すことができます(つまり、通常の関数呼び出し)。

関数の宣言/式を介して作成された関数は、構築可能かつ呼び出し可能です。
矢印関数(およびメソッド)は呼び出しのみ可能です。 classコンストラクターは構築のみ可能です。

呼び出し不可能な関数を呼び出したり、構築不可能な関数を構築しようとすると、ランタイムエラーが発生します。


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

交換可能:

  • 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() {
    // ...
  },
};

コールバック

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

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

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

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

可変長関数

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

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

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

関連する質問:

その他のリソース:

625
Felix Kling

このPlnkrの例を見てください

変数thisは大きく異なりますtimesCalledはボタンが呼ばれるたびに1だけインクリメントします。これが私の個人的な質問に答えます。

.click( () => { } )

そして

.click(function() { })

PlnkrのGuidカウントからわかるように、ループで使用すると、両方とも同じ数の関数が作成されます。

3
abbaf33f