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#call나 Function#apply. ( 이 답변 끝에 호스트 제공 객체 에 대한 경고를 참조하십시오. 그러나 드문 문제입니다.)

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

    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역방향 루프보다 선호하는 이유 는 다음과 같습니다.

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

그런 다음 코드에서 리버스 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. jQuery 와 Underscore.js 는 each단락 될 수있는 루프를 제공 하기 위해 자체 변형 을 제공합니다.


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

세 가지 구현이 있습니다 foreach에 JQuery와 같은 다음은.

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이상한 점을 피하고 다른 언어 in의 for루프 처럼 작동하게 만들고 함수 내에서와 달리 루프 내에서 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와 같은 다른 루프 메커니즘 forEach과 for..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.