ES2015에서 명명 된 화살표 함수를 작성하는 방법


204

ES6 에서 새 화살표 구문으로 변환하려고하는 기능이 있습니다. 명명 된 함수입니다.

function sayHello(name) {
    console.log(name + ' says hello');
}

var 문없이 이름을 지정하는 방법이 있습니까?

var sayHello = (name) => {
    console.log(name + ' says hello');
}

분명히이 기능을 정의한 후에 만 ​​사용할 수 있습니다. 다음과 같은 것 :

sayHello = (name) => {
        console.log(name + ' says hello');
    }

ES6 에서 이것을 수행하는 새로운 방법이 있습니까?


3
화살표 구문의 포인트 아닌가 되지는 함수의 이름을 지정?
AstroCB

64
반드시, 화살표 함수는 어휘 범위를 유지하므로 어휘 범위와 함께 명명 된 함수 (스택 추적에 유용한)를 생성하는 속기가 있으면 매우 유용합니다.
Matt Styles

6
두 번째 스 니펫에 어떤 문제가 있습니까?
Bergi

함수 본문 내에서 할당 된 이름을 참조 할 수 있습니다. var sayHello = (name) => {console.log (sayHello); }; 그리고 재귀 함수의 경우 종종 정확하게 수행합니다. 매우 유용한 예는 아니지만 인수를 얻지 못하면 스스로를 반환하는 함수가 있습니다. var sayHello = (name) => name? console.log (name + 'says hello') : sayHello; sayHello () ( 'frank'); //-> "프랭크가 인사한다"
Dtipson

4
질문의 제목입니다 거대 당신이 (두 번째 조각이다) 기능을 화살표 이름을 방법을 배제했기 때문에, 그 내용에 비해 오해의 소지가.
TJ Crowder

답변:


211

ES2015에서 명명 된 화살표 함수를 작성하는 방법

당신은 당신의 질문에서 배제 한 방식으로 : 변수 또는 속성 이름을 JavaScript 엔진에서 합리적으로 이름으로 사용할 수있는 할당 또는 속성 이니셜 라이저의 오른쪽에 배치하십시오. 다른 건 없어 그것을 할 방법이 있지만, 그 일을하는 것은 정확하고 완전하게 사양이 적용됩니다.

사양에 따라이 함수의 이름은 sayHello다음 과 같습니다.

var sayHello = name => {
    console.log(name + ' says hello');
};

이는 할당 연산자> 런타임 의미론 : 추상 오퍼레이션을 호출 하는 평가에 정의되어 있습니다.SetFunctionName 을 호출 (해당 호출은 현재 1.e.iii 단계에 있음).

와 비슷하게, 런타임 의미 : PropertyDefinitionEvaluation를 호출 SetFunctionName하여 및이 기능을 진정한 이름을 제공합니다 :

let o = {
    sayHello: name => {
        console.log(`${name} says hello`);
    }
};

현대식 엔진은 이미 그러한 문장에 대한 함수의 내부 이름을 설정합니다. Edge에는 여전히 name런타임 플래그 뒤의 함수 인스턴스에서 사용할 수있는 비트가 있습니다 .

예를 들어 Chrome 또는 Firefox에서 웹 콘솔을 열고이 스 니펫을 실행하십시오.

"use strict";
let foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

Chrome 51 이상 및 Firefox 53 이상 (및 실험용 플래그가있는 Edge 13 이상)에서 실행하면 다음이 표시됩니다.

foo.name은 foo입니다.
오류
    foo에서 (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3

foo.name is: foo및을 참고하십시오 Error...at foo.

Chrome 50 및 이전 버전, Firefox 52 및 이전 버전 및 실험용 플래그가없는 Edge에서는 Function#name속성 (아직) 이 없기 때문에 대신 표시됩니다 .

foo.name은 다음과 같습니다. 
오류
    foo에서 (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3

이름이 누락되어 있습니다 foo.name is:,하지만이 되는 스택 추적에 표시. 실제로 함수 에서 name 속성 을 구현하는 것이 다른 ES2015 기능보다 우선 순위가 낮다는 것입니다. 크롬과 파이어 폭스는 이제 그것을 가지고있다. Edge는 플래그 뒤에 있으며 플래그 뒤에는 더 이상 없을 것입니다.

분명히, 나는이 기능을 정의한 후에 만 ​​사용할 수 있습니다

옳은. 화살표 함수 에는 함수 선언 구문 이없고 함수 표현식 구문 만 있으며, 이전 스타일의 명명 된 함수 표현식 ( var f = function foo() { };) 의 이름과 같은 화살표는 없습니다 . 따라서 다음과 같은 것은 없습니다.

console.log(function fact(n) {
    if (n < 0) {
        throw new Error("Not defined for negative numbers");
    }
    return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120

그것을 두 가지 표현으로 나눠야합니다 ( 어쨌든 그렇게해야한다고 주장 합니다 ) .

let fact = n => {
    if (n < 0) {
      throw new Error("Not defined for negative numbers.");
    }
    return n == 0 ? 1 : n * fact(n - 1);
};
console.log(fact(5));

물론 단일 표현식이 필요한 곳에 이것을 배치 해야하는 경우 항상 ... 화살표 기능을 사용할 수 있습니다.

console.log((() => {
    let fact = n => {
        if (n < 0) {
            throw new Error("Not defined for negative numbers.");
        }
        return n == 0 ? 1 : n * fact(n - 1);
    };
    return fact(5);
})()); // 120

나는 그것이 예쁘다고 말하지는 않지만, 절대적으로 단일 표현 래퍼가 필요하다면 작동합니다.


이전 엔진과 같이 이름이 설정되지 않도록하려면 어떻게합니까?
trusktr

1
@ trusktr : 왜 당신이 원하는지 알 수 없지만 그것을 막고 싶다면 : 위의 일을하지 마십시오. 예를 들어 let f = () => { /* do something */ };함수에 이름을 할당하는 동안에는 let g = (() => () => { /* do something */ })();그렇지 않습니다.
TJ Crowder

그게 내가 한 일입니다. 클래스 상속 라이브러리의 사용자가 생각할 필요가없는 내부 변수의 이름을 갖는 것보다 클래스 상속 라이브러리에 의해 생성 된 익명 클래스를 익명으로 만들고 싶습니다. 최종 사용자가 이름을보고 싶습니다. 그들이 수업의 이름을 제공 한 경우에만. ( github.com/trusktr/lowclass )
trusktr

4
@trusktr : 한 가지 예외가 사용자의 목적에 맞을 수 있습니다. 기존 객체 의 속성에 함수를 할당 하면 이름이 설정 o.foo = () => {};되지 않습니다. 함수에 이름을 지정하지 않습니다. 이것은 의도적 정보 유출을 방지하기 위해.
TJ Crowder

86

화살표 구문은 익명 함수의 약자입니다. 익명의 기능은 익명입니다.

명명 된 함수는 function키워드 로 정의됩니다 .


16
@ DenysSéguret에서 언급했듯이 익명 함수의 약어가 아닙니다 . 강제 바인딩 된 함수를 얻게 됩니다. 당신은 여기 transpiled 결과를 볼 수 있습니다 bit.do/es2015-arrow ... 더 나은이 무엇을 의미하는지 이해하기
sminutoli

16
OP가 화살표 기능의 이름을 지정하는 방식을 배제했기 때문에이 답변의 첫 번째 단어는 질문에 대한 답변입니다 . 그러나 나머지 대답은 간단하지 않습니다. 사양에서 추상 SetFunctionName작업 이 사용되는 위치를 확인하십시오 . 스펙과 최신 엔진 모두 let a = () => {};에서 명명 된 함수 (이름은 a)를 정의 합니다 ( 볼 오류가 있음). 그들은 단지 name속성을 지원하지 않습니다 (그러나 사양에 있으며 결국 거기에 도착할 것입니다).
TJ Crowder

4
@ DenysSéguret : 간단히 이름을 지정할있습니다 . 사양에 있습니다. 질문에서 OP가 배제 한 방식으로 수행하면 변수뿐만 아니라 함수에 실제 이름이 부여됩니다.
TJ Crowder

5
@TJCrowder 약간의 정보와 유용한 답변에 감사드립니다 . 나는 이것이 (매우 이상한) 기능을 몰랐다.
Denys Séguret

4
이 답변은 정확하지 않습니다. 질문은 아래 @TJCrowder 님이 올바로 답변했습니다.
Drenai

44

'이름'으로 표시되는 경우 .name 말하면 화살표 기능 속성을 설정 입니다.

대입 식의 오른쪽에 화살표 함수가 정의되어 있으면 엔진은 왼쪽의 이름을 사용하여 화살표 함수를 설정하는 데 사용합니다 ( .name예 :

var sayHello = (name) => {
    console.log(name + ' says hello');
}

sayHello.name //=== 'sayHello'

말했듯이, 귀하의 질문은 '화살표 기능을 끌어 올릴 수 있습니까?'인 것 같습니다. 그 질문에 대한 답은 큰 '아니요'입니다.


1
현재 Chrome 버전에서는 sayHello.name이 여전히 ""입니다. 모든 함수와 마찬가지로 sayHello는 객체이므로 원하는 경우 임의의 속성을 정의 할 수 있습니다. 읽기 전용이므로 "name"에 쓸 수 없지만 sayHello.my_name = "sayHello"; 함수 본문 내에서 그것을 참조하거나 참조 할 수 없기 때문에 그것이 무엇을 얻는 지 확실하지 않습니다.
Dtipson

2
이름이 잘못되었습니다. 이름을 직접 변경할 수는 없지만 다음과 같이 구성 할 수 있습니다. Object.defineProperty (sayHello, 'name', {value : 'sayHello'})
Dtipson

1
"화살표 기능이 오른쪽 [..]에 정의 된 경우"소스는 무엇입니까? 사양에서 찾을 수 없습니다. 인용문에 대한 참조가 필요합니다.
Gajus

@Dtipson : 현대식 엔진이 아직 nameES2015 사양에서 요구하는 모든 곳에서 속성 설정을 구현하지 않았기 때문입니다 . 그들은 그것을 얻을 것이다. Chrome 규정 준수 목록의 마지막 항목 중 하나이며 Chrome 50에도 해당 기능이 없습니다 (Chrome 51이 마지막에 표시). 세부 사항 . 그러나 OP는 특별히 이것을하지 않았다.
TJ Crowder

이 이름을 toString으로 가져올 수 있습니까? 재정의를 시도했지만 함수 본문에 액세스하는 방법을 모르겠습니다.
Qwerty

0

ES7에서 가능할 것으로 보입니다 : https://babeljs.io/blog/2015/06/07/react-on-es6-plus#arrow-functions

주어진 예는 다음과 같습니다.

class PostInfo extends React.Component {
  handleOptionsButtonClick = (e) => {
    this.setState({showOptionsModal: true});
  }
}

ES6 화살표 함수의 본문은이를 둘러싼 코드와 동일한 어휘를 공유하므로 ES7 속성 이니셜 라이저의 범위 지정 방식으로 인해 원하는 결과를 얻습니다.

이것을 babel과 함께 사용하려면 가장 실험적인 ES7 stage 0 구문을 활성화해야했습니다. 내 webpack.config.js 파일에서 babel 로더를 다음과 같이 업데이트했습니다.

{test: /\.js$/, exclude: /node_modules/, loader: 'babel?stage=0'},

6
정확히 명명 된 화살표 함수가 아닙니다. 이것은 생성자에서 인스턴스 메소드를 생성하는 지름길이며, 여기서 어떻게 관련이 있는지 궁금합니다.
Bergi

안녕하세요 @ Bergi, 이것이 원래 저자의 의도인지 확실하지 않지만 객체와 동일한 범위로 명명 된 함수를 만들려고했습니다. 이 기술을 사용하지 않고 클래스 생성자에서이를 적용해야하는 적절한 범위를 갖기를 원합니다. this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
Hamish Currie

8
어, constructor() { this.handleOptionsButtonClick = (e) => {…}; }답변의 코드와 완전히 동일하지만 ES6에서 이미 작동하는 것처럼 쉽게 사용할 수 있습니다 . 사용할 필요가 없습니다 .bind.
Bergi

1
Btw, 나는 당신이 "명명 된 함수"와 "(인스턴스) 방법"그리고 "범위"와 " this컨텍스트"를 혼동하고 있다고 생각합니다
Bergi

1
@tdecs : 그렇습니다. 요르 그는 착각합니다. 라는 명명 된 화살표 함수를 let a = () => {};정의합니다 . 세부 사항 . a
TJ Crowder

0

실제로 화살표 기능의 이름을 지정하는 한 가지 방법처럼 보입니다 (적어도 크롬 77 ...).

"use strict";
let fn_names = {};
fn_names.foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

여기에 이미지 설명을 입력하십시오


이론적으로 babel 매크로를 만들 수 있습니다. fn('yourName', ()=>{})이것은 100 % 올바른 화살표 함수 의미를 유지하거나 "명명 된 화살표 함수 구문"을위한 babel 플러그인을 더 잘 유지할 수 fn yourName() => {}있습니다. 이들 중 하나는 위의 코드로 컴파일됩니다. 나는 이름 화살표 BADA55 그렇게 될 것이라고 생각
데빈 G로드

-1

명명 된 화살표 함수를 작성하려면 LoginClass 라는 클래스가 있고이 클래스 내에 function 이라는 화살표를 작성했습니다.successAuth

    constructor() {

    }

    successAuth = (dataArgs)=> { //named arow function

    }

}

1
답변으로 게시하는 코드에 설명을 추가하면 방문자가 이것이 왜 좋은 답변인지 이해하는 데 도움이됩니다.
abarisone

이것은 OP가 원치 않는 말을하고 2 단계에 불과하고 아마도 ES2017을 만들지 않을 이 제안에 의존합니다 (그러나 ES2018을 만들 가능성이 있다고 생각합니다. 몇 개월 동안). 또한 이전의 여러 답변을 효과적으로 복제하므로 유용하지 않습니다.
TJ Crowder 2012

-2

이것은 ES6입니다

예, 당신이 겪고있는 것은 다음과 같습니다.

const foo = (depth) => {console.log("hi i'm Adele")}
foo -> // the function itself
foo() -> // "hi i'm Adele"

이 예제를 시도했지만 정상적으로 작동합니다. 부정적인 투표를해야 할 이유가 있습니까? 이 사용법으로 인해 원치 않는 부작용이 발생하거나 중요한 점이 누락 되었습니까? 내 의심을 분명히하는 당신의 도움에 감사하겠습니다.
FullMoon

@GaneshAdapa : 추가 정보를 제공하지 않고 OP가 원하지 않는 것을 정확하게 수행하고 있기 때문에 다운 보트가 예상됩니다.
TJ Crowder 2016 년

-2

함수 부분과 화살표 부분을 건너 뛰어 함수를 만들 수 있습니다. 예:

 class YourClassNameHere{

   constructor(age) {
     this.age = age;
   }

   foo() {
     return "This is a function with name Foo";
   }

   bar() {
     return "This is a function with name bar";
   }

 }

let myVar = new YourClassNameHere(50);
myVar.foo();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.