[javascript] JavaScript에서 각 배열에 대해

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

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

forEach(instance in theArray)

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



답변

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]]올바르게하지만 테스트하는 것이 중요합니다.)


답변

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

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

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입니다.


답변

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].
}


답변

뒤로 루프

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 루프의 이점과 공포를 보여주었습니다.


답변

일부 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루프를 사용하십시오 .

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

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


답변

나는 이것이 오래된 게시물이라는 것을 알고 있으며 이미 많은 훌륭한 답변이 있습니다. 좀 더 완전성을 위해 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나쁜 소년을 던져 버릴 수 있습니다.