JavaScript의 자동 세미콜론 삽입 (ASI) 규칙은 무엇입니까?


445

글쎄, 먼저 브라우저 의존적인지 물어봐야합니다.

유효하지 않은 토큰이 발견되면 유효하지 않은 토큰까지 코드 섹션이 유효하며 세미콜론은 토큰 앞에 줄 바꿈이 있으면 토큰 앞에 삽입됩니다.

그러나 세미콜론 삽입으로 인한 버그에 대한 일반적인 예는 다음과 같습니다.

return
  _a+b;

.a는 유효한 토큰이므로이 규칙을 따르지 않는 것 같습니다.

반면에 콜 체인을 끊으면 예상대로 작동합니다.

$('#myButton')
  .click(function(){alert("Hello!")});

누구든지 규칙에 대해 더 깊이 설명하고 있습니까?


22
이다 사양은 ...
마일

33
@Miles 부러진 링크가 아닙니다 ;-) ecma-international.org/publications/standards/Ecma-262.htm
Zach Lysobey

3
p. 참조 상기 인용 된 PDF 중 26 개.
ᴠɪɴᴄᴇɴᴛ


섹션 11.9 자동 세미콜론 삽입
Andrew Lam

답변:


454

우선 자동 세미콜론 삽입 (간결성을 위해 ASI라고도 함)의 영향을받는 명령문을 알아야합니다.

  • 빈 진술
  • var 성명서
  • 표현 문
  • do-while 성명서
  • continue 성명서
  • break 성명서
  • return 성명서
  • throw 성명서

ASI의 구체적인 규칙은 사양 §11.9.1 자동 세미콜론 삽입 규칙에 설명되어 있습니다.

세 가지 경우가 설명됩니다.

  1. 문법에서 허용하지 않는 토큰 ( LineTerminator또는 })이 발견되면 다음과 같은 경우 세미콜론이 앞에 삽입됩니다.

    • 토큰은 이전 토큰과 하나 이상 구분됩니다 LineTerminator.
    • 토큰은 }

    :

    { 1
    2 } 3

    로 변환

    { 1
    ;2 ;} 3;

    NumericLiteral 1첫 번째 조건, 광고 토큰 인 터미네이터 다음을 만족한다.
    2두 번째 조건 인 다음 토큰을 충족 }.

  2. 토큰의 입력 스트림의 끝이 발생하고 구문 분석기가 입력 토큰 스트림을 하나의 완전한 프로그램으로 구문 분석 할 수없는 경우 입력 스트림의 끝에 세미콜론이 자동으로 삽입됩니다.

    :

    a = b
    ++c

    다음으로 변환됩니다.

    a = b;
    ++c;
  3. 이 경우는 문법의 일부 생산에서 토큰을 허용하지만 생산이 제한된 생산 인 경우에 발생합니다. 인 경우 세미콜론이 제한된 토큰 앞에 자동으로 삽입됩니다.

    제한된 제작 :

    UpdateExpression :
        LeftHandSideExpression [no LineTerminator here] ++
        LeftHandSideExpression [no LineTerminator here] --
    
    ContinueStatement :
        continue ;
        continue [no LineTerminator here] LabelIdentifier ;
    
    BreakStatement :
        break ;
        break [no LineTerminator here] LabelIdentifier ;
    
    ReturnStatement :
        return ;
        return [no LineTerminator here] Expression ;
    
    ThrowStatement :
        throw [no LineTerminator here] Expression ; 
    
    ArrowFunction :
        ArrowParameters [no LineTerminator here] => ConciseBody
    
    YieldExpression :
        yield [no LineTerminator here] * AssignmentExpression
        yield [no LineTerminator here] AssignmentExpression

    고전적인 예 ReturnStatement:

    return 
      "something";

    로 변환

    return;
      "something";

4
# 1 : 문법에 의해 허용되지 않는 토큰은 일반적으로 줄 종결자가 아닙니다 (3 번에서 제한된 생산을 의미하지 않는 한)? 괄호를 생략해야한다고 생각합니다. # 2 예제는 ++c명확성 을 위해 삽입 만 보여 주어야하지 않습니까?
Bergi

3
ASI는 실제로 "세미콜론을 삽입"할 필요는 없으며 엔진 파서에서 문장을 종료하기 만하면됩니다.
Aprillion

1
"입력 스트림"이란 무엇입니까? "라인"을 의미합니까? "입력 토큰 스트림"은 이해하기 다소 어렵게 만들고 있습니다.
nonopolarity

사양 링크가 다른 사람에게 적용됩니까? 그로 인해 링크가 죽은 거의 빈 페이지가 생겼습니다.
intcreator

이러한 규칙에 따라 "a [LineBreak] = [LineBreak] 3"의 太極 者 無極 而 生에 의한 아래의 예가 여전히 어떻게 작동하는지 설명하십시오
Nir O.

45

로부터 직선 ECMA-262, 제 5 판 인 ECMAScript 사양 :

7.9.1 자동 세미콜론 삽입 규칙

세미콜론 삽입에는 세 가지 기본 규칙이 있습니다.

  1. 프로그램이 왼쪽에서 오른쪽으로 구문 분석 될 때 토큰 ( 불쾌한 토큰 이라고 함) 문법 생성에서 허용되지 않는 )이 발생하면 다음 중 하나 이상에 해당하는 경우 위반 토큰 앞에 세미콜론이 자동으로 삽입됩니다. 조건은 사실이다 :
    • 문제가되는 토큰은 하나 이상의 토큰으로 이전 토큰과 분리됩니다. LineTerminator .
    • 문제의 토큰은 }입니다.
  2. 프로그램이 왼쪽에서 오른쪽으로 구문 분석 될 때 토큰 입력 스트림의 끝에 도달하고 구문 분석기가 입력 토큰 스트림을 하나의 완전한 ECMAScript로 구문 분석 할 수없는 경우 Program 끝에 도달하고 경우 세미콜론이 자동으로 끝에 삽입됩니다. 입력 스트림.
  3. 프로그램이 왼쪽에서 오른쪽으로 구문 분석 될 때 문법의 일부 생산에서 허용되는 토큰이 발견되지만 생산은 제한된 생산 이며 토큰은 주석 바로 다음에 터미널 또는 비 터미널의 첫 번째 토큰이됩니다. 제한된 프로덕션 내에서 " [ LineTerminator여기 없음 ] "(이러한 토큰을 제한된 토큰이라고 함) 제한된 토큰은 하나 이상의 LineTerminator에 의해 이전 토큰과 분리 된 다음 세미콜론이 제한된 토큰 앞에 자동으로 삽입됩니다.

그러나 이전 규칙에는 추가 재정의 조건이 있습니다. 세미콜론이 빈 명령문으로 구문 분석되거나 해당 세미콜론이 for명령문 헤더의 두 세미콜론 중 하나가되면 세미콜론이 자동으로 삽입되지 않습니다 (12.6 참조). .삼).


44

스펙의 세 가지 규칙을 너무 잘 이해할 수 없었습니다.보다 명확한 영어를 원합니다. 그러나 여기 JavaScript에서 수집 한 내용이 있습니다 : The Definitive Guide, 6th Edition, David Flanagan, O'Reilly, 2011 :

인용문:

JavaScript는 모든 줄 바꿈을 세미콜론으로 취급하지는 않습니다. 일반적으로 세미콜론없이 코드를 구문 분석 할 수없는 경우에만 줄 바꿈을 세미콜론으로 처리합니다.

다른 인용문 : 코드

var a
a
=
3 console.log(a)

JavaScript는 두 번째 줄 바꿈을 세미콜론으로 취급하지 않습니다. 더 긴 명령문 a = 3을 계속 구문 분석 할 수 있기 때문입니다.

과:

JavaScript가 줄 바꿈을 두 번째 줄을 첫 번째 줄의 명령문 연속으로 구문 분석 할 수없는 경우 세미콜론으로 해석한다는 일반적인 규칙에 대한 두 가지 예외. 첫 번째 예외는 return, break 및 continue 문을 포함합니다.

...이 단어 뒤에 줄 바꿈이 나타나면 ... JavaScript는 항상 해당 줄 바꿈을 세미콜론으로 해석합니다.

... 두 번째 예외는 ++ 및 −− 연산자와 관련이 있습니다 ...이 연산자 중 하나를 접미사 연산자로 사용하려면 해당 연산자가 적용되는 식과 같은 줄에 나타나야합니다. 그렇지 않으면 줄 바꿈은 세미콜론으로 처리되고 ++ 또는-는 다음 코드에 적용되는 접두사 연산자로 구문 분석됩니다. 예를 들어 다음 코드를 고려하십시오.

x 
++ 
y

로 해석 x; ++y;되지 않습니다.x++; y

그래서 나는 그것을 단순화하려고 생각합니다.

(1) 일부 키워드가 좋아 후 : 2가지 경우를 제외하고 - 일반적으로, 자바 스크립트는 오랫동안 말이뿐만 코드의 연장으로 취급한다 return, break, continue, 그리고 그것을 보는 경우 (2) ++또는 --새 줄에 다음을 추가합니다 ;이전 줄의 끝에서.

"이해가되는 한 코드의 연속으로 처리"에 대한 부분은 정규 표현식의 욕심 ​​매칭과 같은 느낌을줍니다.

위에서 말했듯이, 그 의미는 return 줄 바꿈 하는 JavaScript 인터프리터는;

(다시 인용 : 다음과 같은 단어 뒤에 줄 바꿈이 나타나는 경우 return ] JavaScript는 항상 줄 바꿈을 세미콜론으로 해석합니다)

이 때문에 고전적인 예는

return
{ 
  foo: 1
}

JavaScript 인터프리터는 다음과 같이 처리하므로 예상대로 작동하지 않습니다.

return;   // returning nothing
{
  foo: 1
}

다음 직후에 줄 바꿈이 없어야합니다 return.

return { 
  foo: 1
}

제대로 작동합니다. after 문 ;을 사용하는 규칙을 따르는 경우 자신을 삽입 할 수 있습니다 ;.

return { 
  foo: 1
};

17

세미콜론 삽입 및 var 문에 대해서는 var를 사용할 때 쉼표를 잊어 버리지 만 여러 줄에 걸쳐 있어야합니다. 누군가 어제 내 코드에서 이것을 발견했습니다.

    var srcRecords = src.records
        srcIds = [];

그것은 실행되었지만 그 효과는 srcIds 선언 / 할당이 전역 적이었습니다. 이전 줄에 var가있는 로컬 선언이 더 이상 적용되지 않았기 때문에 자동 세미콜론 삽입으로 인해 해당 명령문이 완료된 것으로 간주되었습니다.


4
이런 종류의 이유는 내가 jsLint를 사용하는 이유입니다
Zach Lysobey

1
:) 즉각적인 응답 코드 편집기에서 JsHint / 린트 오른쪽
dmi3y

5
@balupton 줄을 끝내는 쉼표를 잊어 버리면 세미콜론이 자동으로 삽입됩니다. 규칙과는 반대로 "gotcha"와 비슷했습니다.
Dexygen

1
나는 balupton이 정확하다고 생각합니다. var srcRecords = src.records srcIds = [];한 줄에 쉼표를 잊어 버리거나 "return a & & b"를 쓰면 아무것도 잊지 않습니다 ...하지만 a 앞에 줄 바꿈은 반환 후 자동 세미콜론을 삽입합니다. 이것은 ASI 규칙에 의해 정의됩니다 ...
Sebastian

3
각 줄에 var( let, const)를 입력하는 선명도가 입력 하는 데 걸리는 시간보다 훨씬 빠르다고 생각합니다.
squidbe

5

내가 찾은 JavaScript의 자동 세미콜론 삽입에 대한 가장 문맥 설명 은 Crafting Interpreters 에 관한 책에서 비롯된 것 입니다.

JavaScript의 "자동 세미콜론 삽입"규칙이 이상합니다. 다른 언어에서는 대부분의 줄 바꿈이 의미가 있다고 생각하고 여러 줄 문장에서 몇 개만 무시해야하는 경우 JS는 그 반대라고 가정합니다. 구문 분석 오류가 발생하지 않는 한 모든 줄 바꿈을 의미없는 공백으로 처리합니다. 그렇다면 문법적으로 유효한 것을 얻기 위해 이전 줄 바꿈을 세미콜론으로 바꾸려고합니다.

그는 당신이 냄새를 맡을 때 그것을 계속 설명합니다 .

이 디자인 노트는 그것이 어떻게 작동하는지, 나쁜 아이디어 인 다양한 방법보다 훨씬 적은 방법에 대해 자세히 설명하면 디자인 디아 트라이브로 바뀔 것입니다. 엉망입니다. JavaScript는 이론적으로 언어를 허용하더라도 많은 스타일 가이드가 모든 문장 다음에 명시 적 세미콜론을 요구하는 유일한 언어입니다.


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