ECMAScript 2015 : for 루프의 const


84

완전한 ECMAScript 2015 구현에서 작동해야하는 두 가지 (또는 둘 다) 코드 조각 중 어느 것입니까?

for (const e of a)

for (const i = 0; i < a.length; i += 1)

내 이해에서 첫 번째 예제는 e각 반복마다 초기화 되기 때문에 작동 합니다. 이것은 i두 번째 버전 의 경우에도 해당되지 않습니까?

기존 구현 (Babel, IE, Firefox, Chrome, ESLint)이 일관 적이 지 const않고 두 루프 변형의 다양한 동작과 함께 완전한 구현을 가지고 있기 때문에 혼란 스럽습니다 . 나는 또한 표준에서 구체적인 요점을 찾을 수 없으므로 많이 감사하겠습니다.


1
CONST 상수가 XX를 들어, 당신이 대신하게 사용해야입니다
팻시 이싸

3
@JamesThorpe 아니요, 제 질문은 단순히 행동이 무엇인지 명확히하려고합니다. 예를 들어, ESLint는 첫 번째 예는 OK (그리고 prefer-const옵션으로 선호 됨 )이고 두 번째 예는 유효하지 않은 것으로 간주합니다 . 대부분의 브라우저 구현은 두 예제 모두 유효하지 않은 것으로 간주합니다.
adrianp 2015-08-13

4
AFAIK 첫 번째는 각 반복마다 다시 초기화되므로 OK입니다. Chrome에서 작동합니다.
lyschoening

@lyschoening 및 이것은 두 번째 예제에도 적용되지 않아야합니까?
adrianp 2015-08-13

4
@adrianp는 확실히 두 번째 예가 아닙니다. 일반 for 루프는 본질적으로 다음과 같습니다.{const i = 0; while(i < a.length) { /* for body */ i += 1}}
lyschoening

답변:


92

다음 for-of 루프가 작동합니다.

for (const e of a)

ES6 사양은이를 다음과 같이 설명합니다.

ForDeclaration : LetOrConst ForBinding

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames

명령형 for 루프는 작동하지 않습니다.

for (const i = 0; i < a.length; i += 1)

이는 루프 본문이 실행되기 전에 선언이 한 번만 평가되기 때문입니다.

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation


3
최종 사양이 아닌 초안에 링크하는 이유는 무엇입니까? ecma-international.org/ecma-262/6.0/index.html . 또한 for루프에 대한 잘못된 평가 규칙을 인용하고 있습니다. const ...표현이 아닙니다. 에 대한 규칙을 확인해야합니다 for ( LexicalDeclaration Expression ; Expression) Statement .
Felix Kling

@FelixKling에는 여전히 이전 링크가 북마크되어 있습니다. 평가 규칙에 대해 맞습니다. 변경 불가능한 바인딩이 정확히 한 번 생성되기 때문에 결론은 여전히 ​​동일해야합니까 (5 단계에서)?
lyschoening

4
맞습니다.하지만 단서는 9 단계에 있다고 생각합니다. consts는 반복마다 다시 선언되지 않습니다.
Felix Kling

4
for (const e of a)최신 버전의 Firefox에서 작동하지 않는 것 같습니다. 나는군요SyntaxError: invalid for/in left-hand side
Chris_F

2
MDN 문서는 또한 "블록 내에서 변수를 다시 할당하지 않으면 let 대신 const를 사용할 수 있습니다."라고 말합니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
필 Gibbins

45

이번에는 사양을 인용하지 않겠습니다. 예를 들어 어떤 일이 발생하는지 이해하는 것이 더 쉽기 때문입니다.

for (const e of a) …

기본적으로 다음과 같습니다.

{
    const __it = a[Symbol.iterator]();
    let __res;
    while ((__res = __it.next()) && !__res.done) {
        const e = __res.value;
        …
    }
}

단순화를 위해 표현식에 e대한 TDZ가 있고 루프가 조기에 종료되는 경우 ( 또는 본문에서) a다양한 __it.return()/ __it.throw(e)호출 이 있다는 것을 무시했습니다 .breakthrow

for (const i = 0; i < a.length; i += 1) …

기본적으로

{
    const i = 0;
    while (i < a.length) {
        …
        i += 1;
    }
}

대조적으로let 하는 constA의 선언 for루프는 각 루프 반복에서 다시 선언되지 않는다 (어쨌든 재실행 - 더 initialiser는 아니다). break첫 번째 반복이 아니라면 i +=여기에 던질 것입니다.


나를 위해 (노드 5.0.0) for-of 루프가 예상대로 작동하지 않습니다. 'let a = [1,3,5], b = []'및 'for (const e of a) {b.push (e)}'후 'b == [1, 1, 1]' . 노드 버그 또는 의도 된 동작? 귀하의 코드에 따라 반복마다 새로운 'const e = __res.value'할당이 예상됩니다.
Jürgen Strobel

2
@ JürgenStrobel : 범위 const가 비슷 var하고 할당을 던지지 않는 오래된 노드 버그 입니다. 엄격 모드를 사용하십시오.
Bergi

나는 이것이 오래되었지만 약간의 수정이 있음을 알고 while ( ( __res = __it.next() ) && !__res.done) {있습니다. 그렇지 않으면 __res될 수있을 테니까요 true또는false
JDB 여전히 모니카 기억

@JDB 감사합니다, 수정되었습니다! Btw 당신이 그것을 편집했다면 나는 괜찮 았을 것입니다.
Bergi

3

두 번째 예제는 i각 반복이 아니라 한 번 선언 되기 때문에 확실히 작동하지 않아야합니다. 이것은 해당 범주의 루프가 작동하는 방식의 함수일뿐입니다.

일반 브라우저에서 시도해 볼 수 있습니다.

for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
  console.log(otherVar)
  otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}

루프 const에서 완전히 허용되지 않는 경우는 아닙니다 for. 그것만 for이 const를 수정할 것입니다.

다음은 유효합니다.

for(const i = 0;;){ break } 
for(const i = 0; i < 10;){ break; } 

다음은 유효하지 않습니다.

for(const i = 0;;){ ++i; break; } 
for(const i = 0;;++i){ if(i > 0) break; }

ES2015 사양을 읽은 후 Firefox가 SyntaxError를 제공하는 이유를 잘 모르겠습니다 (Mozilla의 영리한 사람들이 정확하다고 확신하지만) 예외를 발생시켜야하는 것 같습니다.

환경 레코드에서 새롭지 만 초기화되지 않은 변경 불가능한 바인딩을 만듭니다. 문자열 값 N은 바인딩 된 이름의 텍스트입니다. S가 true이면 바인딩이 초기화되기 전에 바인딩 값에 액세스하려고 시도하거나 초기화 된 후에 설정하면 해당 바인딩을 참조하는 작업의 엄격 모드 설정에 관계없이 항상 예외가 발생합니다. S는 기본값이 false 인 선택적 매개 변수입니다.


출처를 인용하지 않고 어떻게 말할 수 있습니까? 왜이의 경우 것이 const아니라위한 let?
Felix Kling

@FelixKling 어떤 문장에 인용이 필요하다고 생각하십니까? const자신이 재 할당되는 것을 허용하지 않으며 (이는 논쟁되지 않음) 내 예가 for암시 적 기대에 반하는 변수 정의 부분의 작동 방식을 명확하게 보여줍니다 . 의 값은 let변경 될 수 있으며 var주어진 예제 와 기능적으로 동일 하지만 let질문의 일부가 아닙니다.
Kit Sunde

1
그래서 명시 적으로 const i한 번만 선언 된다는 것을 의미 하지만 let i그렇지 않습니까? 어떻게 귀하의 예제는 보여줍니다 var i작동하지 const i. var, const와 사이에 분명한 차이가 있기 때문에 let그가 스펙을 인용하는 const것은 매우 가치가 있다고 생각 합니다.
Felix Kling

1
@FelixKling 당신은 내가 타이핑하는 것을 잘못 읽고 있습니다. 내가 말하고 모든 루프에 대해 한 번 선언의 해당 섹션을. 그런 다음 직교 const값은 한 번만 할당 할 수 있으며 재 선언 시도 const는 작동하지 않습니다. 내 예는 선언이 한 번만 발생한다는 사실을 보여주는 것입니다 const. 질문을하는 사람은의 의미를 이해합니다 . let문제가 아닙니다. 당신이 제안하는 것을 명시 적으로 의미하지 않았습니다. 당신은 잘못 읽었습니다.
Kit Sunde 2015-08-13

3
채팅에서 댓글 작성 :을 사용하는 경우 let각 반복마다 i. This is where I am from from : 과 for(let foo = 0; i < 10; ++i){} 동등하며 둘 다 블록 범위입니다. 와 동일한 동작을 노출 하고 있지만, 일반 루프는하지 않습니다. 그것은 명시 적으로 취급 다르게 (당연 아마도). 단순히 "한 번 선언"이라고 말하지만 너무 많은 IMO를 단순화합니다. (funtion() { for(var i = 0; i < 10; ++i){ (function(i) { }(i)) } }());letconstfor/infor/ofconstletforconst
Felix Kling
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.