ES6 즉시 화살표 기능을 호출


149

왜 Node.js콘솔 (4.1.1 및 5.3.0에서 테스트)에서 작동하지만 브라우저 (Chrome에서 테스트)에서 작동하지 않습니까? 이 코드 블록은 기록하는 익명 함수를 작성하고 호출해야합니다 Ok.

() => {
  console.log('Ok');
}()

또한 위의 노드에서 작동 하지만 작동 하지 않습니다.

n => {
  console.log('Ok');
}()

이것도 아닙니다 :

(n) => {
  console.log('Ok');
}()

이상한 점은 매개 변수가 추가되면 실제로 SyntaxError호출하는 부분에 실제로 a 를 던진다는 것 입니다.


8
좋은 질문. 두 파라미터 버전은 바벨 작업
— CodingIntrigue

2
관심이 (n => { console.log("Ok"); })();없으십니까?
— CodingIntrigue

예 (n => { console.log("Ok"); })(), Chrome 개발자 콘솔에서도 작동
— XCS

3 년 후 답은? 반드시 아래 3 가지 답변 중 하나를 받아 들여야합니까?!
— joedotnot

@ joedotnot 명확한 대답을 얻지 못했습니다. 주로 Node.js의 이상한 구현이었습니다. 최신 버전의 Node.js첫 번째 버전에서는 더 이상 작동하지 않는 것 같습니다.
— XCS

답변:


194

이름을 필요로하지 않고 유효한 JavaScript로 만드는 함수 정의 대신 함수 표현식 으로 만들어야합니다 .

(() => {
  console.log('Ok');
})()

IIFE 와 동일

(function(){
   console.log('Ok')
})();

그리고 이것이 Node.js에서 작동하지만 크롬에서는 작동하지 않는 가능한 이유는 파서가이를 자체 실행 함수로 해석하기 때문입니다.

function() { console.log('hello'); }();

Node.js이것은 잘 작동합니다. 이것은 함수 표현식이며 크롬과 파이어 폭스이며 대부분의 브라우저는이 방식으로 해석합니다. 수동으로 호출해야합니다.

파서가 함수 표현식을 기대하도록 지시하는 가장 널리 사용되는 방법은 JavaScript에서 parens에 명령문을 포함 할 수 없기 때문에 함수 표현식을 parens로 감싸는 것입니다. 이때 파서가 함수 키워드를 만나면 함수 선언이 아니라 함수 표현식으로 구문 분석하는 것을 알게됩니다.

매개 변수가 지정된 버전 과 관련하여 작동합니다.

((n) => {
  console.log('Ok');
})()

4
첫 번째 예제는 작동 Node.js하고 실제로 값을 기록합니다. 내 질문은 왜 작동합니까? 그리고 매개 변수를 추가 할 때 왜 그렇지 않습니까?
— XCS

1
나는에 익숙하고 IIFE코드를 수정하는 방법을 알고 있습니다. 예를 들어, 매개 변수없이 작동했지만 매개 변수를 추가 IIFE할 때 왜 작동하지 않는지 궁금 n합니다.
— XCS

3
나는 downvote하지 않았다, 그러나 노드에서 매개 변수화 된 버전이 아닌 작업을 수행하는 이유 질문은 때 매개 변수없이 동일한 정의는 않습니다 - 그것은 익명 함수의 노드 / 크롬 구현의 차이를 묻는 아니에요
— CodingIntrigue

1
알기 쉽지만 이전에 언급 한 것처럼 질문에 대답하지 않습니다.- 매개 변수없이 정확히 동일한 정의가 수행 될 때 매개 변수화 된 버전이 노드에서 작동하지 않는 이유
— jkris

그러나 function(){}()화살표 기능 과 동등한 기능은 무엇입니까? 함수 객체에 노출 된 함수 표현식을 원하면 그로부터 보호하십시오.
— dabadaba

18

이들 중 어느 것도 괄호없이 작동해서는 안됩니다.

왜?

사양에 따르면 :

  1. ArrowFunction 은 AssignmentExpression 아래 에 나열됩니다.
  2. (A)의 LHS CallExpression는 해야 MemberExpression , SuperCall 또는 CallExpression

그래서 ArrowFunction은 a의 LHS에있을 수 없습니다 CallExpression .


이것이 효과적으로하는 방법을 의미 =>, 해석되어야하는 것은 대입 연산자와 같은 수준의 동일한 종류에 작동하다 =, +=등

의미

  • x => {foo}() 하지 않습니다 될(x => {foo})()
  • 통역사는 다음과 같이 해석하려고 시도합니다. x => ({foo}())
  • 따라서 여전히 SyntaxError입니다.
  • 따라서 인터프리터는 (반드시 잘못된 것이라 판단하고 SyntaxError를 던집니다.

여기 Babel에도 버그가있었습니다 .


이것들은 몇 가지 유효한 포인트이지만 작동하는 첫 번째 버전을 다음과 같이 () => ({console.log('Ok')}())바꾸면 더 이상 작동하지 않습니다. 따라서 실제로 그렇게 해석하지는 않습니다.
— XCS

@Cristy 유효한 Arrow Function 프로덕션이 아닙니다. Object 리터럴 (괄호로 묶음)로 Object를 작성하려고 console.log(...)하는데 유효한 키 이름이 아니라고 생각합니다.
— thefourtheye

@Cristy : 예, 위의 해석 부분 ( "평균"비트)이 정확하지 않을 수 있지만 사양 부분은 내가 알 수있는 한 멀리 있습니다. : 그것은 또한 내가 V8에서 얻을 오류에 맞는 SyntaxError: Unexpected token (합니다 (가리키는 (에 ()끝이 아닌 (의를 console.log(...)).
— TJ Crowder

@ TJCrowder 당신이 옳습니다. 오류 메시지를 변경하고 말하려는 내용이 전달되지 않기 때문에 그 사실을 깨달을 것입니다 (즉 (, 통역사가 유효한 해석을 찾으려고 노력하면서 포기하고 포기했습니다) "이것은 틀렸어 야한다"), 어쨌든 나는 통역사가 실제로 어떻게 작성되는지 모르기 때문에 틀릴 수있다
— Paul S.

이 위치에서 유효한 토큰이 아닌지 궁금합니다. 세미 콜론을 삽입하지 않습니까?
— thefourtheye

2

이와 같은 문제가 발생하는 이유는 콘솔 자체가 현재 대상으로하는 컨텍스트의 전체 범위를 모방하려고하기 때문입니다. 또한 콘솔에 작성한 명령문 및 표현식에서 리턴 값을 캡처하여 결과로 표시되도록 시도합니다. 예를 들어,

> 3 + 2
< 5

여기서는 표현식 인 것처럼 실행되지만 명령문 인 것처럼 작성했습니다. 일반 스크립트에서는 값이 삭제되지만 여기서는 전체 명령문을 함수 컨텍스트 및 명령문으로 랩핑하는 것과 같이 코드가 내부적으로 엉망이 return되어 발생하는 문제를 포함하여 모든 종류의 이상한 효과가 발생합니다.

이는 스크립트의 일부 ES6 코드가 제대로 작동하지만 Chrome 개발자 도구 콘솔에서는 작동하지 않는 이유 중 하나입니다.

노드 및 Chrome 콘솔에서 이것을 실행하십시오.

{ let a = 3 }

노드 또는 <script>태그에서는 정상적으로 작동하지만 콘솔에서는을 제공합니다 Uncaught SyntaxError: Unexpected identifier. 또한 VMxxx:1평가 된 소스를 검사하기 위해 클릭 할 수 있는 형식으로 소스에 대한 링크를 제공합니다 .

({ let a = 3 })

왜 이렇게 했습니까?

대답은 결과를 호출자에게 반환하고 콘솔에 표시 할 수 있도록 코드를 표현식으로 변환해야한다는 것입니다. 명령문을 괄호로 묶어 표현식을 작성할 수 있지만, 위의 블록은 구문 상 올바르지 않습니다 (표현식은 블록 선언을 가질 수 없음).

콘솔은 코드에 대해 똑똑하여 이러한 엣지 사례를 해결하려고 시도하지만이 답변의 범위를 벗어납니다. 버그를 수정하여 문제를 고칠 수 있는지 확인할 수 있습니다.

다음은 매우 유사한 좋은 예입니다.

https://stackoverflow.com/a/28431346/46588

코드를 작동시키는 가장 안전한 방법은 코드를 표현식으로 실행하고 SyntaxError소스 링크를 검사 하여 실제 실행 코드가 무엇인지 확인하고 그로부터 솔루션을 리버스 엔지니어링하는 것입니다. 일반적으로 전략적으로 배치 된 괄호 쌍을 의미합니다.

간단히 말해 콘솔은 가능한 한 정확하게 글로벌 실행 컨텍스트를 에뮬레이션하려고하지만 v8 엔진 및 JavaScript 시맨틱과의 상호 작용 제한으로 인해 해결하기가 어렵거나 불가능한 경우가 있습니다.


1
그것은 요점입니다. 매개 변수에 관심이 있지만 매개 변수 세트에서는 작동하지 않습니다.
— XCS

네 요점이 보여요 차이점은 Chrome 개발자 도구 콘솔이 실제로 코드를 실행하는 방식에 있습니다. 이를 반영하여 답변을 편집하겠습니다.
— Klemen Slavič

0

나는 이런 질문을했다 :

@getify이 질문을했습니다 : #IIFE 패턴을 생성하기 위해 함수 선언 주위에 paran을 사용하여 함수 표현식으로 변환 한 다음 호출합니다. 이제 화살표 기능 IIFE에서 왜 우리는 paran이 필요합니까?! 화살표 함수는 기본적으로 이미 표현식이 아닙니까?!

그리고 이것은 Kyle Simpson의 답변입니다.

화살표 함수 는 expr이지만 "연산자 우선 순위"(sorta)의 주변 parens b / c가 필요하므로 arrow-IIFE를 호출하는 마지막 parens는 본문의 마지막 토큰이 아니라 전체 함수에 적용됩니다. .

x => console.log(x)(4)

vs

(x => console.log(x))(4)

— 2020 년 6 월 12 일 getify (@getify)


내 질문은 왜 다른 컴파일러가 아닌 일부 컴파일러에서 작동했는지였습니다.
— XCS


당신은 옳습니다, 다르게 행동하지만 JavaScript 사양은 모두 동일합니다. 나는 어느 것이 옳았는지, JS 사양 이이 사건에 대해 무엇을 말하고 있으며, 인수없이 작동하지만 인수로 작동하지 않는 방법에 대해 궁금합니다. 더 기술적 인 답변을 찾고있었습니다.
— XCS

귀하의 예는 매우 분명합니다. 첫 번째 경우 실제로 호출해야합니다 console.log(x)(4).
— XCS

나는 여기서 추측하고 있지만 다음과 같이 설명하는 것이 매우 합리적이라고 생각합니다. 화살표 함수 표현식에서 매개 변수를 사용하지 않을 때 우리는 반드시 파 렌스를 사용해야하며 이는 엔진이 화살표임을 분명히합니다. 함수 표현식,하지만 우리는 하나의 매개 변수가 때 괄호없이 아주 명확 될 수있는 임의이다가이 함수와 그 엔진, 우리는 전체 함수 표현식 주위에 괄호 한 쌍을 넣어 가지고 혼란을 해결하기 위해 혼란
— Ershad을 Qaderi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.