'화살표 함수'와 '함수'는 동일하거나 교환 가능합니까?


520

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

5
ES2015의 인기가 높아짐에 따라 화살표 기능에 대한 비슷한 질문이 점점 더 많이 발생하고 있습니다. 나는이 문제에 대한 좋은 정식 질문 / 답변이 있다고 생각하지 않아서이 문제를 만들었습니다. 이미 좋은 것이 있다고 생각되면 알려주십시오.이 복제본을 닫거나 삭제합니다. 예제를 개선하거나 새로운 예제를 추가하십시오.
Felix Kling

2
JavaScript ecma6는 일반 기능을 화살표 기능으로 변경하는 것은 어떻습니까? 물론, 일반적인 질문은 정식으로 작성된 것만 큼 좋고 일반적 일 수는 없습니다.
Bergi

이 Plnkr 예제를보십시오 . 변수 thistimesCalled버튼을 호출 할 때마다 1 씩만 매우 다릅니다 . 어떤 개인적인 질문에 답 .click( () => { } )하고 .click(function() { }) 당신이 Plnkr의 가이 드 카운트에서 볼 수 있듯이 루프에서 사용할 때 두 함수의 같은 번호를 생성합니다.
abbaf33f

답변:


750

tl; dr : 아니요! 화살표 함수와 함수 선언 / 표현은 동일하지 않으며 맹목적으로 바꿀 수 없습니다.
당신은 않습니다 대체 할 기능하면 되지 사용 this, arguments및 호출되지 않고 new, 다음 네.


자주 : 그것은 따라 달라집니다 . 화살표 함수는 함수 선언 / 표현과 동작이 다르므로 차이점을 먼저 살펴 보겠습니다.

1. 어휘 thisarguments

화살표 함수에는 자체 this또는 arguments바인딩 이 없습니다 . 대신, 이러한 식별자는 다른 변수와 같이 어휘 범위에서 분석됩니다. 그 수단 화살표 함수 내에 있음 thisarguments의 값을 참조 this하고 arguments화살표 기능하는 환경에서 정의 된 (즉, "외부"화살표) 함수에서 :

// 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

함수 표현식의 경우, this내부에 작성된 오브젝트를 참조하십시오 createObject. 화살표 함수의 경우 this를 말한다 thiscreateObject자체.

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생성자는 구성 가능합니다.

호출 할 수없는 함수를 호출하거나 구성 할 수없는 함수를 구성하려고하면 런타임 오류가 발생합니다.


이것을 알면 다음과 같이 말할 수 있습니다.

교체 가능 :

  • 기능은 사용하지 않는 thisarguments.
  • 함께 사용되는 기능 .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), 당신은 할 수없는 화살표 기능을 사용!

가변 기능

화살표 함수에는 자체 기능이 없으므로 화살표 함수로 arguments간단히 바꿀 수 없습니다. 그러나, ES2015은 사용하는 대신 도입 arguments: 나머지 매개 변수를 .

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

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

관련 질문 :

추가 자료 :


6
어휘 this는 또한 영향을 미치며 super아무런 영향을 미치지 않는다고 언급 할 가치가 있습니다 .prototype.
loganfsmyth

1
또한 그것들은 구문 상 상호 교환이 불가능하다는 것을 언급하는 것이 좋습니다. 화살표 함수 ( AssignmentExpression)는 함수 표현식 ( PrimaryExpression)이 가능한 모든 곳에서 떨어질 수 없으며 사람들을 상당히 자주 트립합니다 (구문 분석이 있기 때문에) 주요 JS 구현의 오류).
JMM

@JMM : "사람들을 상당히 자주 여행합니다" 구체적인 예를 제시 할 수 있습니까? 사양을 넘어 서면, FE를 배치 할 수 있지만 AF는 할 수없는 장소는 어쨌든 런타임 오류를 초래할 것 같습니다 ...
Felix Kling

물론, 나는 함수 표현식 ( () => {}()) 과 같은 화살표 함수를 즉시 호출하거나 같은 것을하는 것과 같은 것을 의미 x || () => {}합니다. 이것이 의미하는 바는 런타임 (구문 분석) 오류입니다. (이 경우에도 상당히 자주 사람들은 오류가 잘못되었다고 생각합니다.) 구문 분석하거나 실행할 때 반드시 오류가 아니기 때문에 알 수없는 논리 오류를 다루려고합니까? new하나는 런타임 오류입니까?
JMM

다음은 그 중 일부 링크는 야생에서오고있다 : substack / 노드 browserify # 1499 , 바벨 / 바벨 - eslint # 245 (이 비동기 화살표이지만, 나는 그것이 같은 기본적인 문제라고 생각), 그리고 문제의 무리에 지금 찾기 힘든 바벨이지만 여기 T2847이 있습니다.
JMM

11

화살표 기능 => 지금까지 최고의 ES6 기능. ES6에 강력하게 추가되어 끊임없이 사용합니다.

잠깐, 코드의 어느 곳에서나 화살표 기능을 사용할 수 없으며 화살표 기능을 사용할 수없는 모든 경우에는 작동 this하지 않습니다. 의심의 여지없이 화살표 기능은 코드 단순성을 제공하는 큰 추가 기능입니다.

그러나 동적 컨텍스트가 필요한 경우 화살표 함수를 사용할 수 없습니다. 메소드를 정의하고 생성자를 사용하여 오브젝트를 작성하고 이벤트를 처리 할 때 대상을 가져옵니다.

다음과 같은 이유로 화살표 기능을 사용해서는 안됩니다.

  1. 그들은 가지고 있지 않다 this

    “어휘 범위”를 사용하여“”의 가치가 무엇인지 파악 this합니다. 간단한 단어 어휘 범위 지정에서는 this함수 본문 내부에서 " "를 사용합니다 .

  2. 그들은 가지고 있지 않다 arguments

    화살표 함수에는 arguments객체 가 없습니다 . 그러나 나머지 매개 변수를 사용하여 동일한 기능을 수행 할 수 있습니다.

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

  3. 그들은 함께 사용할 수 없습니다 new

    화살표 함수는 프로토 타입 속성이 없기 때문에 해석자가 될 수 없습니다.

화살표 기능을 사용하는 경우와 사용하지 않는 경우 :

  1. 우리는 이것을 접근 할 수 없기 때문에 객체 리터럴에서 속성으로 함수를 추가하는 데 사용하지 마십시오.
  2. 함수 표현식은 객체 메소드에 가장 적합합니다. 기능과 같은 콜백 또는 방법에 가장 적합 화살표 map, reduce또는 forEach.
  3. 이름으로 호출 할 함수 (호이스트되기 때문에)에 함수 선언을 사용하십시오.
  4. 콜백에는 화살표 기능을 사용하십시오.

2
그들은 인수를 가지고 있지 않습니다, 죄송합니다 사실이 아닙니다, 하나는 ... 연산자를 사용하지 않고 인수를 가질 수 있습니다, 아마도 당신은 인수로서 배열을 가지고 있지 않다고 말하고 싶습니다
Carmine Tambascia

@CarmineTambascia arguments여기 화살표 기능으로는 사용할 수없는 특수 객체 에 대해 읽어보십시오 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
vichle

0

와 함께 화살표 함수를 사용하기 위해 function.prototype.call객체 프로토 타입에서 도우미 함수를 만들었습니다.

  // Using
  // @func = function() {use this here} or This => {use This here}
  using(func) {
    return func.call(this, this);
  }

용법

  var obj = {f:3, a:2}
  .using(This => This.f + This.a) // 5

편집하다

당신은 도우미가 필요하지 않습니다. 당신은 할 수 있습니다 :

var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.