JavaScript 변수는 외부 또는 내부 루프를 선언합니까?


213

AS3에서는 성능 향상을 위해 루프 외부의 모든 변수를 초기화해야한다고 생각합니다. JavaScript에서도 마찬가지입니까? 어느 쪽이 더 좋고 / 빠른 / 가장 좋은 방법입니까?

var value = 0;

for (var i = 0; i < 100; i++)
{
    value = somearray[i];
}

또는

for (var i = 0 ; i < 100; i++)
{
    var value = somearray[i];
}

7
외부! 항상 밖에.
BGerrissen

37
흠, Javascript와 AS3 모두에서 변수 선언이 함수 범위로 푸시되지 않습니까? 내가 맞다면 정말 중요하지 않습니다.
쓰셨

3
@Andy-함수 본문에서 선언하기 전에 할당을 시도 했습니까? 아마도 당신의 선입견은 당신을 타락으로 이끌고 있습니다. 푸쉬 업 범위 지정 기능이있는 WRT 성능은 JS가 해석되면 루프 블록 내에서 추가주기를 씹을 것입니다. 컴파일하면 (대부분의 엔진이 수행하는) 중요하지 않습니다.
쓰셨

2
좋은 질문입니다! 감사. 모든 답변을 읽은 후에는 작은 루프 또는 임시 변수 만 필요한 곳에 유지하고 성능에 영향을 미치지 않는다고 생각합니다. var이 함수 내에서 두 번 이상 사용된다면, 함수 내에서 변수를 참조하고 마지막으로 전역 변수를 참조하면 fn () 외부에 앉을 수 있습니다
Dean Meehan

3
아무도 성능을 측정하려고하지 않은 것에 놀랐습니다. jsperf를 만들었습니다 . Chrome과는 반대로 Safari와 Firefox의 루프 내에서 선언하면 조금 더 빠를 것 같습니다.
Buzut

답변:


281

없습니다 차이 절대적으로 자바 스크립트 또는 ActionScript의 의미 나 성능은.

var파서에 대한 지시문이며 런타임에 실행되는 명령이 아닙니다 . var함수 식별자 (*)에서 특정 식별자가 한 번 이상 선언 된 경우 블록에서 해당 식별자의 모든 사용은 로컬 변수를 참조합니다. 루프 내부, 루프 외부 또는 둘 다에 value선언 되는지 여부 는 차이가 없습니다 var.

결과적으로 가장 읽기 쉬운 것을 작성해야합니다. Crockford에 동의하지 않습니다. 모든 변수를 함수의 맨 위에 두는 것이 항상 가장 좋은 것입니다. 변수가 코드 섹션에서 임시로 사용되는 경우 var해당 섹션에서 선언 하는 것이 더 좋으므로 섹션은 독립형이며 복사하여 붙여 넣을 수 있습니다. 그렇지 않으면 리팩토링하는 동안 관련 코드를 따로 따로 이동하지 않고 몇 줄의 코드를 새 함수에 복사하여 붙여 넣으면 var실수로 글로벌하게됩니다.

특히:

for (var i; i<100; i++)
    do something;

for (var i; i<100; i++)
    do something else;

Crockford는 두 번째를 제거하도록 권장합니다 var(또는 vars를 제거 하고 var i;위 의 작업을 수행 하십시오). 그러나 IMO var는 함수 상단에 여분의 쉽게 잊혀진 코드 비트 를 두지 않고 모든 관련 코드를 함께 유지하면서 두 가지를 모두 유지하는 것이 더 쉽습니다.

개인적으로 필자 var는 독립적 인 코드 섹션에서 변수의 첫 번째 할당으로 같은 함수의 다른 부분에서 동일한 변수 이름을 별도로 사용하는지 여부 를 선언하는 경향이 있습니다. 나에게 var전혀 선언 하지 않는 것은 바람직하지 않은 JS 사마귀이다. JavaScript에서 ANSI C의 [이전 개정] 제한 사항을 복제하는 것이 내 의무로 보지 않습니다.

(* : 중첩 함수 본문 이외)


4
나는 여전히 내가 Crockford에 있는지 여부를 결정할 수 없습니다. 블록 내에서 변수를 선언하는 것은 물론 :) #confused 그러나, 나는 당신의 점에 동의 ... 조금 (장난 꾸러기 인) 조건부 함수 문을 사용하여 같은 느낌
다니엘 Vassallo

20
+1 저는 Crockford의 추론 (Daniel의 답변에 인용)에 동의하지 않습니다. JavaScript 개발자는 다른 "C 계열"프로그래머가 이해할 수 있도록 코드를 작성해서는 안됩니다. if 블록과 루프가 var 내부에서 종종 더 의미가 있기 때문에 var를 사용 합니다.
Andy E

4
-1 OP는 루프 시작 전에 루프 본문의 변수를 선언해야하는지 묻습니다. 루프의 인덱스 값은 분명히 특별한 경우이며 게양되어 OP에 전혀 도움이되지 않습니다.
mkoistinen

21
루프 인덱스는 특별한 경우가 아니며 일반 할당과 동일한 방식으로 처리 및 호이스트됩니다.
bobince

31
+1 Crockford는 이것 (그리고 다른 것, 그러나 나는 틀렸다)에 대해 틀렸다. var함수 상단에서만 사용 하는 것은 우발적 인 전역 변수 생성을 요구하는 것입니다. 그리고 한곳에서 선언 된 많은 관련되지 않은 변수를 갖는 것은 의미 상 의미가 없습니다. 특히 이러한 변수 중 일부는 사용되지 않을 수 있습니다.
MooGoo

64

이론적으로 언어에는 블록 범위가 없으며 함수 범위 만 있기 때문에 JavaScript에서 아무런 차이가 없어야합니다.

성능 인수에 대해서는 확실하지 않지만 Douglas Crockford는 여전히 var함수 문에서 첫 번째 명령문이어야한다고 권장합니다 . JavaScript 프로그래밍 언어에 대한 코드 규약 에서 인용 :

JavaScript에는 블록 범위가 없으므로 블록에 변수를 정의하면 다른 C 계열 언어에 익숙한 프로그래머가 혼동 될 수 있습니다. 함수 상단에 모든 변수를 정의하십시오.

다음 예에서 볼 수 있듯이 그는 요점이 있다고 생각합니다. 함수 상단에 변수를 선언하면 독자가 변수 ifor루프 블록 의 범위에 있다고 생각하는 것을 혼동해서는 안됩니다 .

function myFunction() {
  var i;    // the scope of the variables is very clear

  for (i = 0; i < 10; i++) {
    // ...
  }
}

8
JS 범위에 대한 OP 진실을 알려주는 +1 다른 말로 답을 내리는 것이 궁금합니다!
쓰셨

1
@ Kiranmaine : 성능에 영향을 미치지 않는다고 말하지 않았습니다. 나는 단지 성능과 무관하게 루프 외부에 그것들을 넣는 것에 대한 논쟁을했다 .... 나는 성능 주장에 대한 언급이 없지만 당신은 당신의 대답 중 어느 것도 인용하지 않았다 :)
Daniel Vassallo

1
@ Kiranmaine : 그 소스가 있습니까?
Andy E

5
@Kieranmaine : AFAIK는 루프 내부에서 변수를 선언하더라도 ecma- / javascript런타임에 변수 를 충돌시킵니다. 이를 "게양"이라고합니다. 따라서 차이가 없어야합니다.
jAndy

1
ES6는 let이 답변에 어떤 영향을 줍니까?
jbyrd

58

ECMA-/Javascript언어 hoists기능의 정상에 어디 선언 된 모든 변수입니다. 이 언어가 있기 때문이다 않는function scope와 않습니다 하지block scope다른 언어 C와 같은처럼.
이라고도합니다 lexical scope.

당신이 같은 것을 선언하면

var foo = function(){
    for(var i = 0; i < 10; i++){
    }
};

이것은 hoisted:

var foo = function(){
    var i;
    for(i = 0; i < 10; i++){
    }
}

따라서 성능에 아무런 차이가 없습니다 (그러나 여기서 완전히 틀렸다면 정정하십시오). 함수의 최상위가 아닌 다른 곳에서 변수를 선언 하지 않는
훨씬 더 좋은 주장 은 가독성 입니다. 내에서 변수를 선언하면 이 변수가 아니라 루프 본문 내에서 액세스 할 수 있다는 잘못된 가정으로 이어질 수 완전히 잘못 . 실제로 현재 범위 내 어디에서나 해당 변수에 액세스 할 수 있습니다.for-loop


허용되는 답변과 동일한 기본 답변이지만 IMO는 더 읽기 쉽고 정보를 제공합니다. 좋은 작업.
Anne Gunn

5
ES6는 let이 답변에 어떤 영향을 줍니까?
jbyrd

13

내년에는 모든 브라우저에 코드를 사전 컴파일하는 JS 엔진이 있으므로 성능 차이 (동일한 코드 블록을 반복해서 구문 분석하고 할당을 실행함으로써 발생)는 무시할 수있을 것입니다.

또한 필요한 경우가 아니면 성능을 최적화하지 마십시오. 변수를 처음 필요한 곳에 가깝게 유지하면 코드를 깨끗하게 유지할 수 있습니다. 부정적인 측면에서, 블록 범위를 가진 언어에 익숙한 사람들은 혼란 스러울 수 있습니다.


6

우리가 지금 let그리고 constES2015에서 또 다른 고려 사항 은 변수를 루프 블록으로 구체적으로 범위 지정할 수 있다는 것입니다. 따라서 루프 외부에서 동일한 변수가 필요하지 않은 경우 (또는 각 반복이 이전 반복에서 해당 변수에 수행 된 작업에 의존하는 경우) 다음을 수행하는 것이 좋습니다.

for (let i = 0; i < 100; i++) {
    let value = somearray[i];
    //do something with `value`
}

4

방금 Chrome에서 간단한 테스트를 수행했습니다. 브라우저 에서 바이올린 을 시도하고 결과를 확인하십시오

  var count = 100000000;
    var a = 0;
    console.log(new Date());

    for (var i=0; i<count; i++) {
      a = a + 1
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
      a = a + 1;
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
        var x;
        x = x + 1;
    }

    console.log(new Date());

결과는 마지막 테스트에 ~ 8 초가 걸리고 이전 2 개는 ~ 2 초에 불과합니다. 순서에 관계없이 매우 반복적으로.

그래서 이것은 나에게 증명합니다. 루프 외부에서 항상 변수를 선언해야합니다. 궁금한 점 i은 for () 문에서 선언 한 첫 번째 사례 입니다. 이것은 인덱스를 미리 선언 한 두 번째 테스트만큼 빠르다.


14
@KP : 결과는 직접 테스트하거나 많은 사람들이 확인한 경우에만 입증됩니다. @ mkoistinen : 더 공정한 테스트 jsfiddle.net/GM8nk을 구성했습니다 . Chrome 5에서 스크립트를 여러 번 실행 한 후 일관된 승자가 없음을 알 수있었습니다. 몇 가지 새로 고침 후 세 가지 변형이 모두 다른 것보다 더 잘 수행되었습니다. 나에게서 -1, 나는 두렵다. 브라우저를 다른 브라우저에서 실행할 수도 있습니다 . IE와 Fx는 1 억 반복을 좋아하지 않았습니다.
Andy E

1
@ 앤디 와우,이 간단한 테스트를 기반으로 IE는 100 배 더 빨라? =)
mkoistinen

2
때로는 속도 차이가 크지 만 크로스 브라우저 우승자는 분명하지 않습니다. 기묘한. 앤디의 바이올린은 더 나은 테스트라고 생각합니다. 각 후보를 자체 함수에 넣습니다 ... 원래 스크립트가 함수 외부에서 실행 var되는 경우 전역 변수로 선언하는 것처럼 실제로 테스트하지 않아야합니다. 어쨌든 세계적이다.
bobince

4
사실 이후 1 년 동안,하지만 SHAPOW
sdleihssirhc

2
이것은 내 것이 아니지만 jsperf.com/var-in-for-loop
m1에

1

JavaScript는 C 또는 C ++로 맨 아래에 작성된 언어이므로 어떤 언어인지 잘 모르겠습니다. 그리고 그 목적 중 하나는 내부 메모리 처리의 노력을 절약하는 것입니다. C 또는 C ++에서도 변수가 루프 내에서 선언 될 때 많은 리소스를 소비할지에 대해 걱정할 필요가 없습니다. JavaScript로 왜 걱정해야합니까?


1
C 또는 C ++는 JavaScript의 맨 아래에있을 수 있습니다. 그러나 브라우저는 JavaScript를 기본 언어 (C, C ++)로 변환합니다. 따라서 성능은 브라우저에 따라 다릅니다
Kira

3
@Kira 실제로 C / C ++로 변환되지는 않습니다. Javascript는 JS 런타임 (예 : 브라우저에서 실행되는 가상 머신)에 의해 실행되는 명령 세트로 컴파일됩니다. 동일한 원칙이 Python 및 Ruby와 같은 다른 동적 언어에도 적용됩니다.
안토니 E

@AnthonyE, 정보 주셔서 감사합니다. JS를 C 또는 C ++로 변환하는 것에 대해 확신하지 못했습니다. 그래서 나는 내 의견에 있을 수 있습니다
Kira

0

글쎄, 그것은 달성하려는 것에 달려 있습니다 ... value루프 블록 내부의 임시 변수 일뿐 이라면 두 번째 형태를 사용하는 것이 훨씬 명확합니다. 또한 더 논리적이고 장황합니다.


임시 변수를 포함하여 모든 변수 선언을 맨 위로 밀어 넣으면 실제로 '잡음'이 생겨 혼란을 초래할 수 있습니다.
Daniel Sokolowski

0

for 루프 내부 또는 외부에서 변수를 선언해도 차이가 없습니다. 다음은 테스트 할 샘플 코드입니다.

function a() {
   console.log('Function a() starts');
   console.log(new Date());
    var j;
    for (j=0; j<100000000; j++) {
        var x;
        x = x + 1;
    }
    console.log(new Date());
    console.log('Function a() Ends');
}
a()
function b() {
console.log('Function B() starts');
   console.log(new Date());
    var a;
    var j;
    for (j=0; j<100000000; j++) {
      a = a + 1;
    }
    console.log(new Date());
    console.log('Function B() Ends');
}
b()

제 경우에 결과가 나타났습니다

Function a() starts
VM121:3 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:9 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:10 Function a() Ends
VM121:14 Function B() starts
VM121:15 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:21 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:22 Function B() Ends

감사합니다-MyFavs.in


두 경우 모두 루프 외부에서 j를 선언합니다! X_x
john ktejik

I는 크롬과 81을 시도 let하는 대신 vara()약간 느린 경향이있다 (VS (120) (115), MS = ~ 6 % = IMO 미미 등)
mikiqex

-1

여기서 질문은 기본적으로 루프 내부에 var를 선언하는 것입니다. 이렇게하면 어떻게 될지 생각해보십시오.

var a = 30;
var a = 50;
var a = 60;

이것이 옳다고 생각합니까? 아니요 ... 변수를 여러 번 선언하고 싶지 않기 때문에. 루프 내부에서 변수를 선언하면 루프가 여러 번 선언되지 않습니까? 분명히 '엄격한 사용'모드에있을 때 당신을 때릴 것입니다. 사람들은 원래 질문에 대해 생각하지 않고 Crockford에 동의하지 않았습니다.

따라서 변수를 맨 위에 선언하는 것이 좋습니다. 1. 가독성을 높이기 위해, 2. 좋은 습관을 기르십시오.


1
"루프 안에서 변수를 선언 할 때 루프가 몇 번이나 실행되지 않습니까?" <-아니요, 옳지 않습니다. 변수 선언은 게양되어 있으므로 남은 것은 할당입니다.
Matthias

-2

Linux OS에서 Chrome, Firefox 및 jsperf에서 테스트를 실행 한 후 성능과 관련하여 루프에서 변수 선언과 루프 외부에서 성능 차이가있는 것으로 보입니다. 그것은 작은 차이이지만 반복 횟수와 변수 선언의 양에 의해 더욱 복잡해집니다.

따라서 최상의 성능을 위해서는 루프 외부에서 변수를 선언하는 것이 좋습니다. 또는 변수를 줄에 선언하는 것이 좋습니다. 예를 참조하십시오.

// inline
for (var ai = 0, al = 100000000, av; ai < al; ai++) {
    av = av + 1;
}

// outside
var bv;
var bl = 100000000;
for (var bi = 0; bi < bl; bi++) {
    bv = bv + 1;
}

변수 'al'과 'av'가 for 루프 선언 줄에 어떻게 있는지 확인하십시오. 이 인라인 선언은 지속적으로 더 나은 성능을 제공했습니다. 루프 외부에서 변수를 선언하는 경우에도 마찬가지입니다. 다시 성능 차이는 매우 작습니다.

https://jsperf.com/outside-inline-for-loop-ase/1


나를 위해 당신의 테스트는 루프 내부에서 이루어졌습니다. 그러나 그렇지 않았다면, 그 차이는 결론을 내리기에는 너무 작으며, 받아 들여진 대답 은 차이가 없음을
Ulysse BN

변수 선언이 들어 있기 때문에 실제로 차이는 없습니다.
trincot
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.