카테고리 보관물: 자바스크립트

자바스크립트

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

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

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

forEach(instance in theArray)

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



답변

  • 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나쁜 소년을 던져 버릴 수 있습니다.