JavaScript에서 각 배열에 대해


4682

JavaScript를 사용하여 배열의 모든 항목을 반복하는 방법은 무엇입니까?

나는 이것이 다음과 같다고 생각했다.

forEach(instance in theArray)

theArray내 배열은 어디에 있지만 이것은 잘못된 것 같습니다.


16
나는 그것을 찾아 보았지만, forEach 단지 뿐만 아니라 찾아 보았습니다 for. 언급 한 바와 같이, C #에서이 조금 달랐다, 그것은 :) 저를 혼동
Dante1986

6
ECMAScript & nbsp; 6은 "for ... of"구문을 포함 할 것입니다. 자세한 내용 MDN ( for ... of )을 참조하십시오. 최신 Firefox 버전으로 이미 사용해 볼 수 있습니다.
Slaven Rezic

36
JavaScript의 Array에 대해 Array.ForEach는 for ()보다 약 95 % 느립니다. 이 성능 테스트를 온라인으로보십시오 : coderwall.com/p/kvzbpa 를 통한 jsperf.com/fast-array-foreach
molokoloco

77
95 % 느려진 많은 상황에서 중요한 블로그
David Sykes

7
반대로 파이썬 에서는 전통적인 for 루프를 사용하는 것보다 함수를 사용 하는 것이 더 효율적 입니다. (즉 고려 i < len하고 i++오히려 인터프리터보다는, 엔진에 의해 수행 할 수 있습니다.)
joeytwiddle

답변:


7019

TL; DR

  • for-in안전 장치와 함께 사용하거나 그것이 왜 당신을 물릴 수 있는지 알지 못한다면 사용 하지 마십시오 .
  • 가장 좋은 건은 보통

    • for-of루프 (ES2015 + 만)
    • Array#forEach( spec| MDN) (또는 그 친척 some등) (ES5 + 만 해당),
    • 단순한 구식 for루프
    • 또는 for-in안전 장치와 함께.

그러나 거기 많이 읽어, 탐험 더 ...


JavaScript에는 배열 및 배열과 유사한 객체를 반복하는 강력한 의미가 있습니다. 대답은 두 가지 부분으로 나뉩니다. 순수 배열 옵션과 객체, 다른 반복 가능한 객체 (ES2015 +), DOM 컬렉션 등과 같이 배열 과 비슷한 항목에 대한 옵션 arguments.

당신이 ES2015 옵션을 사용할 수있는 나는 빨리 알게 될 것이다 지금 에 의해, 심지어 ES5 엔진에 transpiling ES5에 ES2015을. 자세한 내용은 "ES2015 transpiling"/ "ES6 transpiling"을 검색하십시오.

자, 우리의 옵션을 보자.

실제 배열의 경우

당신은 세 가지 옵션이 있습니다 인 ECMAScript 5 ( "ES5을") 버전은 가장 광범위 순간에 지원, 2 개의 더 추가 ECMAScript를 2015 ( "ES2015", "ES6") :

  1. 사용 forEach및 관련 (ES5 +)
  2. 간단한 for루프를 사용하십시오
  3. 올바르게 사용for-in
  4. 사용 for-of(이터레이터를 암시 적으로 사용) (ES2015 +)
  5. 반복자를 명시 적으로 사용하십시오 (ES2015 +)

세부:

1. 사용 forEach및 관련

ArrayES5에 의해 추가 된 기능 (직접 또는 폴리 필 사용)에 액세스 할 수있는 모호한 현대 환경 (IE8이 아님)에서 forEach( spec| MDN)를 사용할 수 있습니다 .

var a = ["a", "b", "c"];
a.forEach(function(entry) {
    console.log(entry);
});

forEach콜백 함수 및 선택적으로 this해당 콜백을 호출 할 때 사용할 값 (위에서 사용되지 않음)을 수락합니다 . 배열의 각 항목에 대해 콜백이 호출되어 희소 배열의 존재하지 않는 항목은 건너 뜁니다. 위의 인수 하나만 사용했지만 콜백은 세 가지로 호출됩니다. 각 항목의 값, 해당 항목의 색인 및 반복하는 배열에 대한 참조 ).

IE8 (2016 년 9 월이 글을 쓰는 시점에 NetApps가 시장 점유율을 4 % 이상으로 표시)과 같은 오래된 브라우저를 지원하지 않는 한, forEachshim없이 범용 웹 페이지에서 행복하게 사용할 수 있습니다 . 더 이상 사용되지 않는 브라우저를 지원해야하는 경우에는 shimming / polyfilling forEach을 쉽게 수행 할 수 있습니다 (여러 옵션의 경우 "es5 shim"검색).

forEach 반복 함수에 인수로 제공되므로 포함 범위에서 인덱싱 및 값 변수를 선언 할 필요가 없다는 장점이 있습니다.

각 배열 항목에 대한 함수 호출의 런타임 비용이 걱정된다면 걱정하지 마십시오. 세부 사항 .

또한 forEach"모두 반복"기능이지만 ES5는 다음과 같은 몇 가지 유용한 "어레이를 통해 작업하고 작업을 수행"기능을 정의했습니다.

  • every(콜백이 처음 반환 될 때 루핑이 중지 false되거나 잘못된 것)
  • some(콜백이 처음 반환 될 때 루핑이 중지 true되거나 사실이 아닙니다)
  • filter(필터 함수가 리턴하는 요소를 포함하는 새로운 배열을 작성하고 리턴하는 요소는 true생략 함 false)
  • map (콜백에서 반환 한 값으로 새 배열을 만듭니다)
  • reduce (콜백을 반복해서 호출하여 이전 값을 전달하여 값을 작성합니다. 세부 사항에 대한 스펙을 참조하십시오.
  • reduceRight(와 reduce같지만 오름차순이 아닌 내림차순으로 작동)

2. 간단한 for루프를 사용하십시오

때로는 오래된 방법이 가장 좋습니다.

var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

배열의 길이가 루프 동안 변경되지 않습니다, 그것은 (가능성) 성능에 민감한 코드의 경우, 앞까지 길이를 잡아 약간 더 복잡한 버전은 수 있습니다 작은 비트 빠른 :

var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

그리고 / 또는 뒤로 계산 :

var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

그러나 최신 JavaScript 엔진을 사용하면 마지막 주스를 피할 필요가 거의 없습니다.

ES2015 이상에서는 인덱스 및 값 변수를 for루프에 로컬로 만들 수 있습니다 .

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
    console.log(index, value);
}
//console.log(index);   // would cause "ReferenceError: index is not defined"
//console.log(value);   // would cause "ReferenceError: value is not defined"

그리고 그렇게 할 때, 각 루프 반복에 대해 다시 생성 될 value뿐만 아니라 index다시 생성되므로 루프 본문에서 생성 된 클로저 는 해당 반복에 대해 생성 된 index(및 value)에 대한 참조를 유지합니다 .

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        console.log("Index is: " + index);
    });
}

5 개의 div가있는 경우 첫 번째를 클릭하면 "Index is : 0"이 표시되고 마지막을 클릭하면 "Index is : 4"가 표시됩니다. 대신 대신 사용하면 작동 하지 않습니다 .varlet

3. 올바르게 사용for-in

사람들에게 당신에게 사용하라고 말하게 할 입니다 . for-in그러나 그것이 아닙니다for-in . 배열의 인덱스가 아닌 객체for-in열거 가능한 속성을 반복합니다 . ES2015 (ES6)에서도 주문이 보장 되지 않습니다. ES2015 +는 개체 속성에 순서를 정의하지 않습니다 (통해 [[OwnPropertyKeys]], [[Enumerate]]그리고 그것들을 사용하는 것을 좋아 Object.getOwnPropertyKeys), 그러나 그 정의하지 않았다 for-in순서를 따를 것입니다; 그러나 ES2020은 그렇게했다. ( 이 다른 답변에 대한 자세한 내용 )

for-in배열에 대한 유일한 실제 사용 사례 는 다음과 같습니다.

  • 그것은이다 스파 스 배열대규모 , 그 격차를 나
  • 요소가 아닌 속성을 사용하고 있으며 루프에 포함하려는 경우

첫 번째 예만 살펴보기 : for-in적절한 보호 조치를 사용하는 경우 희소 배열 요소를 방문하는 데 사용할 수 있습니다 .

// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These checks are
        /^0$|^[1-9]\d*$/.test(key) &&    // explained
        key <= 4294967294                // below
        ) {
        console.log(a[key]);
    }
}

세 가지 확인 사항에 유의하십시오.

  1. 객체는 그 이름에 따라 자체 속성을 가지고 있으며 (프로토 타입에서 상속 된 속성이 아님)

  2. 키는 모두 10 진수 (예 : 과학적 표기법이 아닌 일반 문자열 형식)이며

  3. 숫자로 강제 변환 될 때 키의 값은 <= 2 ^ 32-2 (4,294,967,294)입니다. 그 번호는 어디에서 왔습니까? 그것은 사양에서 배열 인덱스의 정의의 일부입니다 . 다른 숫자 (정수가 아닌 숫자, 음수, 2 ^ 32-2보다 큰 숫자)는 배열 인덱스가 아닙니다. 이 2 ^ 32의 이유 - 2 - 즉, 2 ^ 32 이상의 낮은 최대 인덱스 값이다하게 배열의 최대 값이고 length가질 수있다. (예를 들어, 배열의 길이는 32 비트 부호없는 정수에 맞습니다.) ( 이전 블로그 테스트에서 내 이전 테스트가 옳지 않다는 의견을 지적한 RobG에게 요청합니다 .)

물론 인라인 코드에서는 그렇게하지 않을 것입니다. 유틸리티 함수를 작성합니다. 혹시:

4. 사용 for-of(이터레이터를 암시 적으로 사용) (ES2015 +)

ES2015는 반복자 를 JavaScript에 추가했습니다 . 반복자를 사용하는 가장 쉬운 방법은 새로운 for-of문장입니다. 다음과 같이 보입니다 :

const a = ["a", "b", "c"];
for (const val of a) {
    console.log(val);
}

커버 아래에서 배열에서 반복자 를 가져 와서 루프를 통해 값을 가져옵니다. for-in객체 (배열)에 의해 정의 된 반복자를 사용하고 배열 이 속성이 아닌 항목을 통해 반복되도록 정의하기 때문에 using에 문제가 없습니다 . for-inES5 와 달리 항목을 방문하는 순서는 색인의 숫자 순서입니다.

5. 반복자를 명시 적으로 사용하십시오 (ES2015 +)

때로는 반복자를 명시 적으로 사용하고 싶을 수도 있습니다 . 그것보다 훨씬 복잡하지만 그렇게 할 수도 있습니다 for-of. 다음과 같이 보입니다 :

const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

반복자는 사양의 반복자 정의와 일치하는 객체입니다. 그 next방법은 새 반환 결과 객체 당신이 그것을 호출 할 때마다. 결과 객체에는 속성이 있으며 done, 완료 여부를 알려주는 속성 value과 해당 반복 값이 있는 속성 이 있습니다. (있는 done경우 선택 사항 false이며, 원하는 value경우 선택 사항 undefined입니다.)

의 의미 value는 반복자 에 따라 다릅니다. 배열은 반복자를 반환하는 (적어도) 세 가지 함수를 지원합니다.

  • values(): 이것은 내가 위에서 사용한 것입니다. 그것은 각각 반복자 반환 value이 반복 배열 항목이다 ( "a", "b""c"실시 예 이전에).
  • keys(): 각각 value이 해당 반복에 대한 키인 반복자를 리턴합니다 (따라서 a위의 경우 "0", 그런 "1"다음 "2").
  • entries(): 각각 value[key, value]해당 반복 양식의 배열 인 반복자를 리턴합니다 .

배열과 같은 객체

실제 배열 외에도 숫자 이름을 가진 속성과 속성을 가진 배열과 같은 객체가 있습니다 length. NodeList인스턴스, arguments객체 등. 우리는 내용을 어떻게 반복합니까?

배열에 대해 위의 옵션 중 하나를 사용하십시오

위의 배열 접근법 중 적어도 일부, 또는 대부분 또는 전체는 종종 배열 유사 객체에 동일하게 적용됩니다.

  1. 사용 forEach및 관련 (ES5 +)

    다양한 기능들은 Array.prototype"의도적 일반"이며 일반적 통해 객체와 같은 배열에 사용될 수있다 Function#callFunction#apply. ( 이 답변 끝에 호스트 제공 객체대한 경고를 참조하십시오. 그러나 드문 문제입니다.)

    당신이 사용하고자 가정하자 forEachA의 NodechildNodes속성입니다. 당신은 이것을 할 것입니다 :

    Array.prototype.forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });

    그렇게 많이 할 경우, 함수 참조의 사본을 재사용을 위해 변수로 가져와야 할 수 있습니다. 예를 들면 다음과 같습니다.

    // (This is all presumably in some scoping function)
    var forEach = Array.prototype.forEach;
    
    // Then later...
    forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
  2. 간단한 for루프를 사용하십시오

    분명히 간단한 for루프는 배열과 같은 객체에 적용됩니다.

  3. 올바르게 사용for-in

    for-in배열과 동일한 보호 장치를 사용하면 배열과 유사한 객체에서도 작동해야합니다. 위의 # 1에 호스트 제공 개체에 대한 경고가 적용될 수 있습니다.

  4. 사용 for-of(이터레이터를 암시 적으로 사용) (ES2015 +)

    for-of객체가 제공 하는 반복자를 사용 합니다 (있는 경우). 여기에는 호스트 제공 객체가 포함됩니다. 예를 들어, NodeListfrom querySelectorAll에 대한 스펙이 반복을 지원하도록 업데이트되었습니다. 의 사양 HTMLCollection에서가 getElementsByTagName아니었다.

  5. 반복자를 명시 적으로 사용하십시오 (ES2015 +)

    # 4를 참조하십시오.

진정한 배열 만들기

다른 경우에는 배열과 유사한 객체를 실제 배열로 변환 할 수 있습니다. 그렇게하는 것은 놀라 울 정도로 쉽습니다.

  1. slice배열 의 방법을 사용하십시오

    slice위에서 언급 한 다른 방법들과 마찬가지로 "의도적으로 일반적"인 배열 의 방법을 사용할 수 있으므로 다음 과 같이 배열과 같은 객체와 함께 사용할 수 있습니다.

    var trueArray = Array.prototype.slice.call(arrayLikeObject);

    예를 들어, NodeLista를 실제 배열로 변환하려면 다음과 같이하십시오.

    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));

    아래의 호스트 제공 객체에 대한주의 사항을 참조하십시오 . 특히, 이것은 IE8 및 이전 버전에서는 실패하므로 호스트 제공 객체를 this이와 같이 사용할 수 없습니다 .

  2. 스프레드 구문 사용 ( ...)

    이 기능을 지원하는 JavaScript 엔진과 함께 ES2015의 스프레드 구문 을 사용할 수도 있습니다 . 마찬가지로 객체에서 제공 for-of하는 반복자를 사용 합니다 (이전 섹션의 # 4 참조).

    var trueArray = [...iterableObject];

    예를 들어, NodeList스프레드 구문을 사용하여 a를 실제 배열로 변환하려는 경우 이것은 매우 간결합니다.

    var divs = [...document.querySelectorAll("div")];
  3. 사용하다 Array.from

    Array.from (사양) | (MDN) (ES2015 +, 쉽게 폴리 필됨)은 배열과 유사한 객체로부터 배열을 생성하고, 선택적으로 매핑 기능을 통해 항목을 먼저 전달합니다. 그래서:

    var divs = Array.from(document.querySelectorAll("div"));

    또는 주어진 클래스가있는 요소의 태그 이름 배열을 얻으려면 매핑 함수를 사용하십시오.

    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });

호스트 제공 객체에 대한주의 사항

호스트 제공 배열 유사 객체 (DOM 목록 및 JavaScript 엔진이 아닌 브라우저에서 제공하는 기타 Array.prototype기능)와 함께 함수 를 사용하는 경우 대상 환경에서 테스트하여 호스트 제공 객체가 제대로 작동하는지 확인해야합니다. . 대부분은 올바르게 동작 하지만 (지금) 테스트하는 것이 중요합니다. 그 이유는 사용하려는 대부분의 방법이 호스트 제공 객체에 의존하여 추상 작업에 정직한 답변을 제공하기 때문 입니다. 이 글을 쓰는 시점에서 브라우저는이 작업을 훌륭하게 수행하지만 5.1 사양에서는 호스트 제공 객체가 정직하지 않을 수 있습니다. §8.6.2있으며 , 해당 섹션의 시작 부분 근처에 큰 테이블 아래에 여러 단락이 있습니다.Array.prototype[[HasProperty]]

호스트 객체는 달리 명시되지 않는 한 어떤 방식 으로든 이러한 내부 메소드를 구현할 수 있습니다. 예를 들어, 하나의 가능성이 있다는 것입니다 [[Get]][[Put]]특정 호스트 객체가 실제로 가져오고 저장하는 속성 값을하지만 [[HasProperty]]항상 생성 거짓 .

(ES2015 사양에서 동등한 언어를 찾을 수는 없지만 여전히 그렇습니다.) 다시 말하지만, 현대 브라우저에서 일반적인 호스트 제공 배열과 같은 객체 ( NodeList예 : 예) 처리합니다. [[HasProperty]]올바르게하지만 테스트하는 것이 중요합니다.)


44
또한 .forEach효율적으로 깨지지 않는 것을 추가하고 싶습니다 . 휴식을 수행하려면 예외를 던져야합니다.
Pijusn

82
@Pius : 루프를 중단하려면을 사용할 수 있습니다 some. (나는 forEach또한 침입 을 허용 하고 싶지만, 음, 나에게 묻지 않았다. ;-))
TJ Crowder

6
@TJCrowder 기본 목적이 아니므로 해결 방법처럼 보이지만 True입니다.
Pijusn

8
@ user889030 : ,이후 k=0가 아니라 ;. 프로그래밍은 많은 것들을 기억하십시오. 그중 하나는 세부 사항에주의를 기울입니다 ... :-)
TJ Crowder

5
@ JimB : 그것은 위에 설명되어 length있으며 방법이 아닙니다. :-)
TJ Crowder 2016

513

참고 :이 답변은 절망적 인 구식입니다. 보다 현대적인 접근 방식 은 배열에서 사용 가능한 방법을 살펴보십시오 . 관심있는 방법은 다음과 같습니다.

  • 각각
  • 지도
  • 필터
  • 지퍼
  • 줄이다
  • ...마다
  • 약간

JavaScript 에서 배열을 반복하는 표준 방법 은 바닐라 for루프입니다.

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element
}

그러나이 방법은 밀도가 높은 배열이 있고 각 인덱스가 요소에 의해 점유 된 경우에만 유용합니다. 배열이 희소 한 경우이 방법을 사용하면 성능 문제가 발생할 수 있습니다 . 배열에 실제로 존재 하지 않는 많은 인덱스를 반복하기 때문 입니다. 이 경우 for .. in-loop가 더 좋습니다. 그러나for..in -loop가 레거시 브라우저에도 열거 되기 때문에 또는 추가 속성이 enumerable.

에서 ECMAScript를 5 배열 프로토 타입에 foreach는 방법이 될 것입니다,하지만 기존의 브라우저에서 지원되지 않습니다. 일관성있게 사용하려면이를 지원하는 환경 (예 : 서버 측 JavaScript의 경우 Node.js )이 있거나 "폴리 필"을 사용해야합니다. 그러나이 기능에 대한 Polyfill은 사소한 것이며 코드를 읽기 쉽게 만들기 때문에 포함하기에 좋은 polyfill입니다.


2
for(instance in objArray) 올바른 사용법 이 아닌 이유는 무엇입니까? 좀 더 단순 해 보이지만 사용법에 대한 올바른 방법이 아니라고 들었습니다.
Dante1986

21
인라인 길이 캐싱을 사용할 수 있습니다. for (var i = 0, l = arr.length; i <l; i ++)
Robert Hoffmann

3
첫 줄 끝의 쉼표가 의도적 인 것입니까, 아니면 오타입니까 (세미콜론 일 수 있습니까)?
Mohd Abdul Mujib

6
@ wardha-Web 의도적입니다. 단일 var키워드로 여러 변수를 선언 할 수 있습니다 . 세미콜론을 사용했다면 element글로벌 범위에서 선언되었을 것입니다 (또는 JSHint가 프로덕션에 도달하기 전에 소리를 지른 것입니다).
PatrikAkerstrand

239

jQuery 라이브러리를 사용하는 경우 jQuery.each 를 사용할 수 있습니다 .

$.each(yourArray, function(index, value) {
  // do your stuff here
});

편집하다 :

질문에 따라 사용자는 jquery 대신 자바 스크립트로 코드를 원하므로 편집은

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

2
아마도이 대답을 가장 자주 사용할 것입니다. 이 질문에 대한 가장 좋은 대답은 아니지만 실제로 jQuery를 사용하는 사람들에게는 가장 간단하고 가장 적합합니다. 나는 우리 모두 바닐라 길을 배워야한다고 생각합니다. 이해를 넓히는 것이 결코 아프지 않습니다.
mopsyd

47
jQuery는 각각 네이티브 솔루션보다 훨씬 느립니다. 가능하면 jQuery 대신 기본 JavaScript를 사용하는 것이 좋습니다. jsperf.com/browser-diet-jquery-each-vs-for-loop
Kevin Boss

8
바닐라 js를 사용할 수있을 때 jQuery를 사용하지 마십시오
Noe

2
표준 JS를
고수

116

뒤로 루프

for 루프는 여기에 언급 할 가치가 있다고 생각합니다 .

for (var i = array.length; i--; ) {
     // process array[i]
}

장점 :

  • 임시 len변수 를 선언 하거나 array.length각 반복에 대해 비교할 필요가 없습니다.이 중 하나는 1 분 동안 최적화 될 수 있습니다.
  • DOM에서 형제 를 역순으로 제거하는 것이 일반적으로 더 효율적 입니다. (브라우저는 내부 배열에서 요소를 덜 이동해야합니다.)
  • 만약 있다면 배열은 수정 또는 인덱스 후에 반복하면서 (예를 들어, 제거 또는 항목을 삽입 array[i]), 그 후 정 루프 위치로 왼쪽으로 이동할 항목을 이동 것이다 I 또는 재 공정 된 I 이었다 번째 항목 오른쪽으로 이동했습니다. 전통적인 for 루프에서는 i 를 처리해야하는 다음 항목을 가리 키도록 업데이트 할 있지만 반복 방향을 반대로 바꾸는 것이 더 단순 하고 더 우아한 솔루션 인 경우가 많습니다 .
  • 마찬가지로 중첩 된 DOM 요소를 수정하거나 제거 할 때 역으로 처리하면 오류피할 수 있습니다 . 예를 들어, 하위 노드를 처리하기 전에 상위 노드의 innerHTML을 수정하십시오. 자식 노드에 도달하면 DOM에서 분리되어 부모의 innerHTML을 작성할 때 새로 만든 자식으로 대체됩니다.
  • 사용 가능한 다른 옵션 중 일부 를 입력하고 읽는 것이 더 짧 습니다 . ES6과 는 잃지 만 .forEach()for ... of

단점 :

  • 항목을 역순으로 처리합니다. 결과에서 새 배열을 작성하거나 화면에 물건을 인쇄 하는 경우 원래 순서에 따라 출력이 자연스럽게 바뀝니다 .
  • 순서를 유지하기 위해 형제를 첫 번째 자식으로 DOM에 반복적으로 삽입하는 것이 덜 효율적 입니다. (브라우저는 계속해서 일을 올바르게 이동해야합니다.) DOM 노드를 효율적이고 순서대로 만들려면 앞으로 루프하고 정상적으로 추가하십시오 (또한 "문서 조각"을 사용하십시오).
  • 리버스 루프는 후배 개발자에게 혼란 을줍니다. (전망에 따라 이점을 고려할 수도 있습니다.)

항상 사용해야합니까?

루프 포워드해야 할 이유가없는 한 일부 개발자 는 기본적으로 역방향 for 루프 사용합니다 .

일반적으로 성능 향상은 미미하지만 비명은 다음과 같습니다.

"목록에있는 모든 항목에이 작업을 수행하면 주문에 신경 쓰지 않습니다!"

그러나입니다 실제로 하지 당신이 때 그 경우 구별하기 때문에, 실제로 의도 신뢰할 수있는 표시 순서에 대해주의를, 정말 할 필요성을 역으로 루프. 실제로 ECMAScript를 포함하여 대부분의 언어에서 사용할 수 없지만 "예 : 신경 쓰지 않음"의도를 정확하게 표현하기 위해서는 다른 구문이 필요합니다 forEachUnordered().

순서가 중요하지 않고 효율성 이 문제가되는 경우 (게임 또는 애니메이션 엔진의 가장 안쪽 루프에서) 역방향 for 루프를 이동 패턴으로 사용하는 것이 좋습니다. 기존 코드에서 역 for 루프를 보는 것이 반드시 순서와 관련 이 없다는 것을 의미하지는 않습니다 !

forEach ()를 사용하는 것이 좋습니다

일반적으로 선명도와 안전 이 더 중요한 고급 코드의 경우 이전 Array::forEach에는 루핑의 기본 패턴으로 사용 하는 것이 좋습니다 (요즘에는을 선호합니다 for..of). forEach역방향 루프보다 선호하는 이유 는 다음과 같습니다.

  • 읽는 것이 더 명확합니다.
  • 그것은을 나타냅니다 (항상 긴에서 가능 깜짝 숨어있는 블록 내에서 이동하지 않을 forwhile루프).
  • 폐쇄의 자유 범위를 제공합니다.
  • 지역 변수의 누출과 외부 변수와의 우연한 충돌 (및 돌연변이)을 줄입니다.

그런 다음 코드에서 리버스 for 루프를 볼 때 이는 좋은 이유 (위에서 설명한 이유 중 하나)로 반전되었다는 힌트입니다. 그리고 전통적인 순방향 for 루프를 보면 시프트가 발생할 수 있음을 나타낼 수 있습니다.

(의도에 대한 논의가 당신에게 이해가되지 않는다면, 당신과 당신의 코드는 Crockford의 Programming Style & Your Brain 에 대한 강의를 보는 것이 도움이 될 것입니다 .)

이제는 사용하는 것이 더 좋습니다.

바람직한 지 for..of또는 forEach()바람직한 지에 대한 논쟁이 있습니다 .

개인적으로, 성능이나 축소가 주요 관심사가되지 않는 한 읽기 쉬운 것처럼 보이는 것을 사용하는 경향이 있습니다. 요즘 그래서 내가 사용하는 것을 선호 for..of대신 forEach(),하지만 난 항상 사용 map또는 filter또는 find또는 some해당되는 경우. (내 동료를 위해 거의 사용하지 않습니다 reduce.)


어떻게 작동합니까?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

당신은 그 통지합니다 i--(우리가 일반적으로 볼 경우 (우리가 일반적으로 비교 참조) 마지막 절은 비어 중간 절입니다 i++). 이는 연속 조건i-- 으로도 사용됨을 의미합니다 . 결정적으로, 각 반복 전에 실행되고 확인 됩니다.

  • array.length폭발하지 않고 어떻게 시작할 수 있습니까?

    각 반복 전에i-- 실행 되기 때문에 첫 번째 반복에서 실제로 범위를 벗어난 배열 항목 array.length - 1과 관련된 문제를 피하는 항목에 액세스합니다 . undefined

  • 인덱스 0 이전의 반복을 멈추지 않는 이유는 무엇입니까?

    조건 i--이 거짓 값으로 평가되면 (0을 생성 할 때) 루프 반복이 중지됩니다 .

    요령은 --i후행 i--연산자 와 달리 감소 하기 전에i 값을 산출한다는 것 입니다. 당신의 콘솔은 이것을 증명할 수 있습니다 :

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    따라서 최종 반복에서 i 는 이전에 1 이었고 i--표현식은 0으로 변경 되었지만 실제로는 1 (거짓)을 산출 하므로 조건이 통과합니다. 다음 반복에서 i-1로i-- 변경 되지만 0 (거짓)이 발생하여 루프 하단에서 즉시 실행이 중단됩니다.

    루프 전통적인 전방에서 i++그리고 ++i(더글라스 크록 퍼드 지적한 바와 같이) 교환 할 수있다. 그러나 역 for 루프에서는 감소가 조건 표현식이기 때문에 i--인덱스 0에서 항목을 처리 하려면 고수해야합니다 .


하찮은 일

어떤 사람들은 리버스 for루프 에 작은 화살표를 그리고 윙크로 끝나기를 좋아합니다 .

for (var i = array.length; i --> 0 ;) {

크레딧은 WYL로 이동하여 리버스 for 루프의 이점과 공포를 보여주었습니다.


3
나는 벤치 마크 를 추가 하는 것을 잊었다 . 또한 6502와 같은 8 비트 프로세서에서 리버스 루핑이 어떻게 중요한 최적화를했는지 언급하지 않았습니다. 여기서 실제로 무료로 비교할 수 있습니다!
joeytwiddle

동일한 대답이 여기에 훨씬 더 간결하게 제공 됩니다 (다른 질문에).
joeytwiddle

84

일부 C 스타일 언어는 foreach열거를 반복 하는 데 사용 됩니다. JavaScript에서 이것은 for..in루프 구조로 수행됩니다 .

var index,
    value;
for (index in obj) {
    value = obj[index];
}

캐치가 있습니다. for..in객체의 열거 가능한 각 멤버와 프로토 타입의 멤버를 반복합니다. 객체의 프로토 타입을 통해 상속 된 값을 읽지 않으려면 속성이 객체에 속하는지 확인하면됩니다.

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

또한 ECMAScript 5콜백을 사용하여 배열을 열거하는 데 사용할 수 있는 forEach방법을 추가했습니다 Array.prototype(폴리 필은 문서에 있으므로 여전히 오래된 브라우저에서 사용할 수 있습니다).

arr.forEach(function (val, index, theArray) {
    //do stuff
});

Array.prototype.forEach콜백이를 반환 할 때 중단되지 않는다는 점에 유의해야 합니다 false. jQueryUnderscore.jseach단락 될 수있는 루프를 제공 하기 위해 자체 변형 을 제공합니다.


3
그렇다면 일반적인 for 루프 또는 C 스타일 언어에서와 같은 foreach 루프 에서처럼 ECMAScript5 foreach 루프를 어떻게 벗어날 수 있습니까?
Ciaran Gallagher

5
@CiaranG, JavaScript 에서는 루프를 벗어나는 데 사용할 each수있는 메소드 를 보는 것이 일반적 return false이지만 forEach이 방법으로는 옵션이 아닙니다. 외부 플래그를 사용할 수 있습니다 (예를 들어 if (flag) return;, 나머지 함수 본문의 실행 만 막을 forEach수 있음). 여전히 전체 콜렉션에 대해 계속 반복됩니다.
zzzzBov

43

배열을 반복하려면 표준 3 파트 for루프를 사용하십시오 .

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

캐싱 myArray.length또는 반복 하여 일부 성능 최적화를 얻을 수 있습니다 .


6
에 대한 (var i = 0, 길이 = myArray.length; i <길이; i ++)해야 할 일
Edson Medina

5
@EdsonMedina 또한라는 새로운 전역 변수를 만듭니다 length. ;)
joeytwiddle

4
@joeytwiddle 네,하지만이 글의 범위를 벗어납니다. 어쨌든 전역 변수 i를 작성합니다.
Edson Medina

6
@EdsonMedina 나의 사과, 나는 완전히 잘못했다. ,과제를 사용한 후에도 새로운 글로벌이 소개 되지 않으므로 제안은 괜찮습니다 ! 다른 문제로 이것을 혼동했습니다 =. 할당을 사용 하면 새로운 전역 이 만들어 집니다.
joeytwiddle

변수 i가 루프에 로컬 이 아님을 주의하십시오 . JavaScript에는 블록 범위가 없습니다. var i, length, arrayItem;이 오해를 피하기 위해 루프 전에 선언하는 것이 좋습니다 .
James

35

나는 이것이 오래된 게시물이라는 것을 알고 있으며 이미 많은 훌륭한 답변이 있습니다. 좀 더 완전성을 위해 AngularJS를 사용하여 다른 것을 던질 것이라고 생각했습니다 . 물론 이것은 Angular를 사용하는 경우에만 적용됩니다. 그럼에도 불구하고 어쨌든 넣고 싶습니다.

angular.forEach2 개의 인수와 선택적인 세 번째 인수를 사용합니다. 첫 번째 인수는 반복 할 객체 (배열)이고 두 번째 인수는 반복자 함수이며 선택적 세 번째 인수는 객체 컨텍스트 (기본적으로 루프 내에서 'this'라고 함)입니다.

각도의 forEach 루프를 사용하는 방법에는 여러 가지가 있습니다. 가장 단순하고 아마도 가장 많이 사용되는 것은

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

한 배열에서 다른 배열로 항목을 복사하는 데 유용한 또 다른 방법은

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

그렇게 할 필요는 없지만 간단하게 다음을 수행 할 수 있으며 이전 예제와 동일합니다.

angular.forEach(temp, function(item) {
    temp2.push(item);
});

이제 angular.forEach내장 바닐라 풍미 for루프 와 달리 기능 을 사용하는 장단점이 있습니다.

찬성

  • 쉬운 가독성
  • 손쉬운 쓰기
  • 가능한 경우 angular.forEachES5 forEach 루프를 사용합니다. forEach 루프가 for 루프보다 훨씬 느리므로 단점 섹션에서 효율성을 얻을 것 입니다. 일관성 있고 표준화 된 것이 좋기 때문에 이것을 전문가라고 언급합니다.

다음과 같은 2 개의 중첩 루프를 고려하십시오. 두 개의 객체 배열이 있고 각 객체에 결과 배열이 포함되어 있다고 가정 해 봅시다. 각 배열에는 문자열 (또는 기타)의 Value 속성이 있습니다. 그리고 각 결과에 대해 반복해야하며 결과가 같으면 몇 가지 조치를 수행하십시오.

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

이것은 매우 간단한 가상의 예이지만, 두 번째 접근 방식을 사용하여 루프 용 트리플 임베디드를 작성했으며 그 문제를 읽고 쓰기 가 매우 어려웠습니다.

단점

  • 능률. angular.forEach, 그리고 forEach그 문제에 대한 네이티브 는 둘 다 일반 루프 보다 훨씬 느리다 for. 약 90 % 느리다 . 따라서 큰 데이터 세트의 경우 기본 for루프 를 따르는 것이 가장 좋습니다 .
  • 휴식, 계속 또는 반환 지원이 없습니다. continue실제로는 " 사고 "에 의해 지원되며 , 함수 에서 계속해서 해당 반복에 대한 함수에서 계속되는 명령문을 angular.forEach넣습니다 . 이것은 또한 원주민 이 휴식이나 계속을 지원하지 않기 때문입니다 .return;angular.forEach(array, function(item) { if (someConditionIsTrue) return; });forEach

나는 다양한 다른 장단점이있을 것이라고 확신하며, 당신이 적합하다고 생각하는 것을 자유롭게 추가하십시오. 결론적으로, 효율성이 필요한 경우 for루핑 요구에 맞는 기본 루프 만 사용하십시오. 그러나 데이터 세트가 더 작고 가독성 및 쓰기 가능성 대신에 약간의 효율성이 포기된다면, 그 angular.forEach나쁜 소년을 던져 버릴 수 있습니다.


34

배열을 비우지 않아도되는 경우 :

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x의 마지막 값을 포함하고 y배열에서 제거됩니다. 를 사용 shift()하여에서 첫 번째 항목을주고 제거 할 수도 있습니다 y.


4
과 같은 희소 배열이 발생하면 작동하지 않습니다 [1, 2, undefined, 3].
M. Grzywaczewski 1

2
... 또는 실제로 잘못된 것 : [1, 2, 0, 3]또는[true, true, false, true]
joeytwiddle

31

foreach는 구현 ( jsFiddle에서 볼 수 ) :

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

2
이 반복자는 불필요한 길이 계산을 수행합니다. 이상적인 경우 목록 길이는 한 번만 계산해야합니다.
MIdhun Krishna

2
@MIdhunKrishna 나는 내 대답과 jsFiddle을 업데이트했지만 생각만큼 간단하지는 않습니다. 이 질문을
nmoliveira

2
전체 및 올바른 구현은 여기에서 찾을 수 있습니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
marciowb

29

아마도 for(i = 0; i < array.length; i++)루프는 최선의 선택이 아닙니다. 왜? 이것이 있다면 :

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

이 메소드는에서 array[0]를 호출 합니다 array[2]. 첫째, 이것은 먼저 가지고 있지 않은 변수를 참조하고, 둘째는 배열에 변수가 없으며, 세 번째는 코드를 더 대담하게 만듭니다. 여기를 보면 내가 사용하는 것입니다.

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

그리고 그것이 기능이되기를 원한다면, 당신은 이것을 할 수 있습니다 :

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

깨고 싶다면 조금 더 논리를 :

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

예:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

다음을 반환합니다.

//Hello
//World
//!!!

29

세 가지 구현이 있습니다 foreachJQuery와 같은 다음은.

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

2
콘솔 로그는 데모 용입니다. 그것은 cmplete 실행 예제로 만드는 것입니다.
Rajesh Paul

29

ECMAScript 6 현재 :

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

여기서 of이상한 점을 피하고 다른 언어 infor루프 처럼 작동하게 만들고 함수 내에서와 달리 루프 내에서 let바인딩 i합니다.

중괄호 ( {})는 하나의 명령 (예 : 위의 예) 만있는 경우 생략 할 수 있습니다.


28

쉬운 해결책은 이제 underscore.js 라이브러리 를 사용하는 것 입니다. 사용 가능한 경우 each작업을 기본으로 자동 위임하는 등의 유용한 도구를 제공 forEach합니다.

작동 방식 의 CodePen 예제 는 다음과 같습니다.

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

또한보십시오


23

for each네이티브 JavaScript 에는 루프 가 없습니다 . 라이브러리를 사용 하여이 기능을 사용하고 ( Underscore.js 권장 ) 간단한 for루프를 사용할 수 있습니다 .

for (var instance in objects) {
   ...
}

그러나 더 간단한 for루프 를 사용해야하는 이유가있을 수 있습니다 (스택 오버플로 질문을 참조하십시오. 배열 반복에서“for… in”을 사용하는 것은 왜 그렇게 나쁜 생각입니까? )

var instance;
for (var i=0; i < objects.length; i++) {
    var instance = objects[i];
    ...
}

22

인덱스가 0에서 시작하는 스파 스가 아닌 목록의 반복자입니다. 이는 document.getElementsByTagName 또는 document.querySelectorAll를 처리 할 때의 일반적인 시나리오입니다.

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

사용 예 :

실시 예 # 1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

실시 예 # 2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

각 p 태그는 class="blue"

실시 예 # 3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

다른 모든 p 태그는 class="red">

실시 예 # 4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

마지막으로 처음 20 개의 파란색 p 태그가 녹색으로 변경되었습니다.

문자열을 함수로 사용시주의 사항 : 함수는 컨텍스트 외부에서 작성되며 변수 범위가 지정된 경우에만 사용해야합니다. 그렇지 않으면 범위가 더 직관적 인 함수를 전달하는 것이 좋습니다.


21

있다 몇 가지 방법 루프 아래로, 자바 스크립트의 배열을 통해 :

대한 - 그건 가장 일반적인 하나 . 루핑을위한 전체 코드 블록

var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

while- 조건이 통과되는 동안 루프. 가장 빠른 루프 인 것 같습니다

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

do / while- 조건이 참인 동안 코드 블록을 반복하면서 한 번 이상 실행됩니다.

var text = ""
var i = 0;

do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);

document.getElementById("example").innerHTML = text;
<p id="example"></p>

기능 루프 - forEach, map, filter, 또한 reduce당신이 등을 배열로 뭔가를 할 필요가 있다면 (그들이 기능을 통해 루프,하지만 그들은 사용

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

배열의 함수형 프로그래밍에 대한 자세한 내용과 예제는 map, filter and reduce : 블로그 JavaScript 함수형 프로그래밍 블로그를 참조하십시오 .


작은 수정 : forEach새로운 기능을 반환하지 않기 때문에 Array(실제로는 아무것도 반환하지 않기 때문에) "기능적"루프가 아닙니다 .
nicholaswmin

19

ECMAScript 5 (JavaScript 버전)는 어레이와 함께 작동합니다.

forEach- 배열의 모든 항목을 반복하고 각 항목에 필요한 모든 작업을 수행합니다.

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is #" + (index+1) + " in the musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

내장 기능을 사용하는 어레이에서의 작업에 더 관심이있는 경우.

맵핑 -이 콜백 함수의 결과 새로운 배열을 생성한다. 이 방법은 배열의 요소를 포맷해야 할 때 사용하는 것이 좋습니다.

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

reduce- 이름에서 알 있듯이 현재 요소와 이전 실행 결과를 전달하는 주어진 함수를 호출하여 배열을 단일 값으로 줄입니다.

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

every- 배열의 모든 요소가 콜백 함수에서 테스트를 통과하면 true 또는 false를 반환합니다.

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
  return elem >= 18;
});

// Output: false

filter- 필터는 주어진 함수에 true를 반환하는 요소를 가진 배열을 반환한다는 점을 제외하고는 모든 것과 매우 유사합니다.

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

16

에 침입 할 수있는 기능이 없습니다 forEach. 실행을 중단하려면 다음 Array#some과 같이 사용하십시오 .

[1,2,3].some(function(number) {
    return number === 1;
});

이것은 some배열 순서로 실행 된 콜백이 true를 반환하고 나머지 실행을 단락시키는 즉시 true를 반환 하기 때문에 작동 합니다. 원래 답변 일부 배열 프로토 타입 참조


13

나는 이것을 역 루프의 구성 과이 구문을 좋아하는 누군가를위한 위의 답변으로 추가하고 싶습니다.

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

장점 :

이것의 이점 : 당신은 이미 다른 줄로 선언 할 필요가없는 것과 같은 첫 번째 참조를 이미 가지고 있습니다. 객체 배열을 통해 루핑 할 때 편리합니다.

단점 :

참조가 거짓-거짓 (정의되지 않은 등) 일 때마다 중단됩니다. 그래도 이점으로 사용할 수 있습니다. 그러나 읽기가 조금 더 어려워 질 것입니다. 또한 브라우저에 따라 원래보다 더 빠르게 작동하도록 "최적화되지"않을 수 있습니다.


12

사용하여 jQuery 방법 $.map:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

1
나는 출력이 더 가능성이 높다고 생각한다 [undefined, 2, undefined, 4, undefined, 6, undefined].

10

ECMAScript를 6 사용 루프 destructuring확산 연산자

스프레드 연산자의 구조화 및 사용은 ECMAScript 6을 처음 사용하는 사람들이 좀 더 사람이 읽을 수 있고 심미적 인 것으로 매우 유용한 것으로 입증되었지만 일부 JavaScript 재향 군인은 지저분한 것으로 간주 할 수 있습니다. 주니어 나 다른 사람들이 유용 할 수 있습니다.

다음 예제는 for...of명령문과 .forEach메소드를 사용합니다 .

실시 예 6, 7, 8 과 같은 기능적인 루프가 사용될 수있다 .map, .filter, .reduce, .sort, .every, .some. 이러한 메소드에 대한 자세한 정보는 Array Object를 확인하십시오 .

예 1 : 노멀 for...of루프-트릭은 없습니다.

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

예 2 : 단어를 문자로 나누기

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);
}

예제 3 : a key와 반복value

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on Internet Explorer  unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

예 4 : 인라인 객체 속성 가져 오기

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

예제 5 : 필요한 것에 대한 심층적 인 객체 속성 얻기

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

예 6 : 예 3 과 함께 사용 됩니까?.forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

예 7 : IS 예 4 와 함께 사용.forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parentheses
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

예 8 : IS 예 5 와 함께 사용.forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});


7

아이디어에 가장 가까운 방법 Array.forEach()은 배열의 각 요소에 대해 실행될 클로저 함수를 받아들이는 것입니다.

myArray.forEach(
  (item) => {
    // Do something
    console.log(item);
  }
);

다른 가능한 방법은 Array.map()동일한 방식으로 작동하지만 다음과 같이 반환하는 모든 값을 가져 와서 새 배열로 반환합니다 (각 요소를 새 요소에 본질적으로 매핑).

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

1
이것은 map배열의 요소를 변경하지 않습니다. 새로운 배열의 항목을 기존 배열의 항목에 적용한 결과이므로 새로운 배열을 반환하기 때문입니다.
Jesús Franco

나는 그것이 새로운 배열을 반환하지 않는다고 말한 적이 없으며 함수에 의해 적용된 변경 사항을 언급하고있었습니다. 그러나 여기에 답을 바꾸겠습니다.
Ante Jablan Adamović

다시 말하지만, 원래 배열의 모든 항목에서 맵이 수정되거나 변경되지 않습니다 . 원래 항목 의 복사본 으로 맵 작업을 강조하는 답변을 제안하고 편집 하여 원래 배열을 그대로 유지합니다.
Jesús Franco

7

다음과 같이 각각을 호출 할 수 있습니다.

forEach제공하는 배열을 반복하고 각 반복마다 반복 element값을 보유합니다. 인덱스가 필요한 경우 iforEach의 콜백 함수에서 두 번째 매개 변수로 as 를 전달하여 현재 인덱스를 얻을 수 있습니다 .

Foreach는 기본적으로 다른 함수를 매개 변수로 사용하는 고차 함수입니다.

let theArray= [1,3,2];

theArray.forEach((element) => {
  // Use the element of the array
  console.log(element)
}

산출:

1
3
2

다음과 같이 배열을 반복 할 수도 있습니다.

for (let i=0; i<theArray.length; i++) {
  console.log(i); // i will have the value of each index
}

6

화살표 기능을 사용하여 객체 배열을 반복하려면 다음을 수행하십시오.

let arr = [{name:'john', age:50}, {name:'clark', age:19}, {name:'mohan', age:26}];

arr.forEach((person)=>{
  console.log('I am ' + person.name + ' and I am ' + person.age + ' old');
})


6

람다 구문은 일반적으로 Internet Explorer 10 이하에서 작동하지 않습니다.

나는 보통

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

jQuery 이고 이미 jQuery 파일이 실행중인 경우 인덱스 및 값 매개 변수의 위치를 ​​반대로 설정해야합니다.

$("#ul>li").each(function(**index, value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

5

대규모 배열을 사용 iterators하는 경우 효율성을 높이기 위해 사용해야 합니다. 반복자는 특정 자바 스크립트 컬렉션의 재산입니다 (같은 Map, Set, String, Array). 심지어, for..of사용 iterator후드 아래.

반복자는 목록의 항목을 마치 스트림 인 것처럼 한 번에 하나씩 사용할 수 있도록하여 효율성을 향상시킵니다. 반복자를 특별하게 만드는 것은 콜렉션을 순회하는 방법입니다. 다른 루프는 전체 컬렉션을 반복해서로드해야하며 반복자는 컬렉션의 현재 위치 만 알면됩니다.

반복자의 next메소드를 호출하여 현재 항목에 액세스합니다 . 다음 메소드는 value현재 항목의 를 반환 boolean하고 컬렉션의 끝에 도달하면 표시합니다. 다음은 배열에서 반복자를 만드는 예입니다.

다음 values()과 같은 방법을 사용하여 일반 배열을 반복자로 변환하십시오 .

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

다음 Symbol.iterator과 같이 일반 배열을 반복자로 변환 할 수도 있습니다 .

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

정규식 array을 다음 iterator과 같이 변형 할 수도 있습니다 .

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

참고 :

  • 반복자는 본질적으로 소진됩니다.
  • iterable기본적으로 개체는 없습니다 . for..in이 경우 값 대신 키와 작동하므로 사용하십시오 .

자세한 내용은 iteration protocol 여기를 참조 하십시오 .


5

를 사용하려면 forEach()다음과 같이 보입니다.

theArray.forEach ( element => {
    console.log(element);
});

를 사용하려면 for()다음과 같이 보입니다.

for(let idx = 0; idx < theArray.length; idx++){
    let element = theArray[idx];
    console.log(element);
}

4

새로운 업데이트 된 기능 ECMAScript 6 (ES6) 및 ECMAScript 2015에 따라 루프와 함께 다음 옵션을 사용할 수 있습니다.

for 루프

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

for ... in 루프

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

Array.forEach ()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

for ... of 루프

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

while 루프

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

루프 동안 ...

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4

4

공연

오늘 (2019년 12월 18일) 내에서 테스트를 수행 맥 OS v10.13.6 크롬 V 79.0에, (높은 시에라), 사파리 v13.0.4 및 파이어 폭스 v71.0 (64 비트) - 최적화에 대한 결론 (및 마이크로 최적화 하는 이점은 적지 만 코드 복잡성이 커지기 때문에 일반적으로 코드에 도입 할 가치가 없습니다.

  • 전통적인 for i( Aa )는 모든 브라우저에서 빠른 코드를 작성하는 것이 좋습니다.

  • 그룹 C의for-of ( Ad ) 와 같은 다른 솔루션은 모두 Aa 보다 2-10 배 이상 느리지 만 작은 배열의 경우 코드 선명도를 높이기 위해 사용하는 것이 좋습니다.

  • n( Ab, Bb, Be )에 캐시 된 배열 길이를 가진 루프 는 때로는 더 빠르며 때로는 그렇지 않습니다. 아마도 컴파일러는 자동으로이 상황을 감지하고 캐싱을 도입합니다. 캐시 된 버전과 캐시되지 않은 버전 ( Aa, Ba, Bd ) 사이의 속도 차이 는 약 1 %이므로 소개 n미세 최적화 입니다.

  • i--루프가 마지막 배열 요소 ( Ac, Bc ) 에서 시작 하는 유사한 솔루션 은 일반적으로 순방향 솔루션보다 ~ 30 % 느립니다. 아마도 CPU 메모리 캐시 작동 방식 일 것입니다. 순방향 메모리 읽기는 CPU 캐싱에 더 적합합니다). 이러한 솔루션을 사용하지 않는 것이 좋습니다.

세부

테스트에서 배열 요소의 합을 계산합니다. 작은 배열 (10 요소)과 큰 배열 (1M 요소)에 대한 테스트를 수행하고 세 그룹으로 나눕니다.

  • - for테스트
  • B - while테스트
  • C- 기타 / 대체 방법

크로스 브라우저 결과

모든 테스트 된 브라우저에 대한 결과

여기에 이미지 설명을 입력하십시오브라우저 **

10 개의 요소로 구성된 배열

Chrome에 대한 결과. 여기 에서 컴퓨터 에서 테스트를 수행 할 수 있습니다 .

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

1,000,000 개의 요소로 구성된 배열

Chrome에 대한 결과. 여기에서 컴퓨터 에서 테스트를 수행 할 수 있습니다

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


4

요약:

배열을 반복 할 때 종종 다음 목표 중 하나를 달성하려고합니다.

  1. 배열을 반복하고 새 배열을 만들고 싶습니다.

    Array.prototype.map

  2. 배열을 반복하고 새 배열을 만들지 않습니다.

    Array.prototype.forEach

    for..of 고리

JavaScript에는이 두 가지 목표를 달성하는 많은 방법이 있습니다. 그러나 일부는 다른 것보다 편리합니다. 아래에서는 JavaScript에서 배열 반복을 수행하기 위해 일반적으로 사용되는 몇 가지 방법 (가장 편리한 IMO)을 찾을 수 있습니다.

새로운 배열 만들기 : Map

map()Array.prototype배열의 모든 요소를 ​​변환 한 다음 배열 을 반환 할 수 있는 함수입니다 . map()콜백 함수를 인수로 받아서 다음과 같은 방식으로 작동합니다.

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

map()인수로 전달한 콜백 은 모든 요소에 대해 실행됩니다. 그런 다음 원래 배열과 길이가 같은 배열이 반환됩니다. 이 새로운 배열 요소는에 인수로 전달 된 콜백 함수에 의해 변환됩니다 map().

사이의 뚜렷한 차이 map와 같은 다른 루프 메커니즘 forEachfor..of루프 즉 map반환에게 새로운 배열과 잎을 그대로 이전 배열 (같은 생각에 당신이 명시 적으로 조작하는 경우를 제외하고를 splice).

또한 map함수의 콜백은 현재 반복의 색인 번호를 두 번째 인수로 제공합니다. 또한 세 번째 인수 map는 호출 된 배열을 제공 합니까? 때로는 이러한 속성이 매우 유용 할 수 있습니다.

루프 forEach

forEach에있는 함수 Array.prototype의 인수로 콜백 함수가 걸린다. 그런 다음 배열의 모든 요소에 대해이 콜백 함수를 실행합니다. 받는 반면 map()기능, foreach는 함수는 아무 것도 반환하지 않습니다 ( undefined). 예를 들면 다음과 같습니다.

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

그냥 같은 map기능의 forEach콜백은 두 번째 인수로 현재 반복의 인덱스 번호를 제공합니다. 또한 세 번째 인수 forEach는 호출 된 배열을 제공 합니까?

사용하여 요소를 반복 for..of

for..of루프는 배열 (또는 다른 반복 가능한 객체)의 모든 요소를 통해 루프. 다음과 같은 방식으로 작동합니다.

let arr = [1, 2, 3, 4, 5];

for(let element of arr) {
  console.log(element * 2);
}

위의 예에서 element배열 요소를 나타내며 arr반복하려는 배열입니다. 이름 element은 임의적이며 'el'과 같은 다른 이름이나이 이름이 적용되는 경우 좀 더 선언적인 이름을 선택할 수 있습니다.

for..in루프와 루프를 혼동하지 마십시오 for..of. for..in루프는 배열의 열거 가능한 모든 속성을 for..of반복 하지만 루프는 배열 요소 만 반복합니다. 예를 들면 다음과 같습니다.

let arr = [1, 2, 3, 4, 5];

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}

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