ES6에서 노드 목록 필터링 또는 매핑


90

ES6에서 노드 목록을 필터링하거나 매핑하는 가장 효율적인 방법은 무엇입니까?

내 측정 값에 따라 다음 옵션 중 하나를 사용합니다.

[...nodelist].filter

또는

Array.from(nodelist).filter

어느 것을 추천 하시겠습니까? 예를 들어 어레이를 사용하지 않는 더 좋은 방법이 있습니까?


2
기본적으로 두 방법 모두 동일한 작업을 수행합니다. 당신이 사용하고 그 babel다음 [...coll]단순히 호출 Array.from(coll)없는 아무것도 Array.
Leonid Beschastny 2015 년

FWIW, ...구문은 이전 IDE에서 지원되지 않을 수 있지만 Array.from()일반적인 방법입니다.
Marat Tanalin 2015 년

답변:


131
  • [...nodelist] 객체가 반복 가능한 경우 객체에서 배열을 만듭니다.
  • Array.from(nodelist)객체가 반복 가능 하거나 객체가 배열과 같은 경우 (has .length및 numeric props) 객체에서 배열을 만듭니다.

NodeList.prototype[Symbol.iterator]두 경우 모두 iterable을 다루기 때문에 두 예제가 있으면 동일합니다 . 그러나 환경 NodeList이 반복 가능 하도록 구성되지 않은 경우 첫 번째 예제는 실패하고 두 번째 예제는 성공합니다. Babel현재이 사건을 제대로 처리하지 못하고 있습니다 .

그래서 당신 NodeList이 반복 가능 하다면 , 당신이 사용하는 것은 당신에게 달려 있습니다. 나는 사례별로 선택할 것입니다. 한 가지 이점은 Array.from매핑 함수의 두 번째 인수를 사용하는 반면 첫 번째 [...iterable].map(item => item)는 임시 배열을 만들어야하지만 Array.from(iterable, item => item)그렇지 않다는 것입니다. 그러나 목록을 매핑하지 않는 경우에는 중요하지 않습니다.


17

TL; DR;

Array.prototype.slice.call(nodelist).filter

slice () 메서드는 배열을 반환합니다. 반환되는 배열 회수 (NodeList의)의 얕은 복사는 것을 이보다 더 빨리 작동 그래서 Array.from () 가 최대한 빨리 작동 그래서 ) (Array.from

원본 컬렉션의 요소는 다음과 같이 반환 된 배열에 복사됩니다.

  • 객체 참조 (실제 객체가 아님)의 경우 slice는 객체 참조를 새 배열로 복사합니다. 원래 배열과 새 배열은 모두 동일한 객체를 참조합니다. 참조 된 객체가 변경되면 변경 사항이 새 배열과 원래 배열 모두에 표시됩니다.
  • 문자열, 숫자 및 부울 (String, Number 및 Boolean 객체가 아님)의 경우 slice는 값을 새 배열에 복사합니다. 한 배열에서 문자열, 숫자 또는 부울을 변경해도 다른 배열에는 영향을주지 않습니다.

인수에 대한 간단한 설명

Array.prototype.slice (beginIndex, endIndex)

  • 선택적 인수 beginIndex 및 endIndex를 사용합니다. 슬라이스가 제공되지 않으면 beginIndex == 0을 사용하므로 컬렉션에서 모든 항목을 추출합니다.

Array.prototype.slice.call (네임 스페이스, beginIndex, endIndex)

  • 개체를 첫 번째 인수로 사용합니다. 컬렉션을 객체로 사용하는 것은 문자 그대로 해당 객체 네임 스페이스 에서 직접 slice 메서드를 호출한다는 것을 의미합니다.

2
제한적이고 즉각적인 도움을 제공 할 수있는이 코드 스 니펫에 감사드립니다. 적절한 설명은 이것이 문제에 대한 좋은 해결책 인 이유를 보여줌으로써 장기적인 가치를 크게 향상시키고 다른 유사한 질문을 가진 미래의 독자에게 더 유용하게 만들 것입니다. 귀하의 가정을 포함하여 몇 가지 설명을 추가하려면 답변을 편집하십시오.
Maximilian Peters

IE가 지원 Array.from되지 않는지 궁금합니다 . IE 시스템을 찾을 시간입니다. 이제 IE10과 IE11에서 Array.from을 사용할 수 있었기 때문에 정말 혼란 스럽습니다. 이 방법은 IE10 + 11에서 작동하지만 모든 문서에서 달리 언급 할 때 Array.from이 작동하는 것에 의해 완화되지 않습니다.
CTS_AE

Array.fromIE11에서 작동하지 않습니다. 개체가 'from'속성 또는 메서드를 지원하지 않습니다
Fus Ro Dah

감사합니다. 이것은 JavaScript의 이전 구현에서 저를 위해 일했습니다
Vic Seedoubleyew

1
Array.from또한 얕은 복사본을 반환합니다. 따라서 .NET보다 빠르게 작동 한다고 결론내리지 못합니다 Array#slice.
로버트

9

NodeList에서 직접 사용 하는 참조 를 찾았습니다.map

Array.prototype.map.call(nodelist, fn)

나는 그것을 테스트하지 않았지만 NodeList에 직접 액세스해야하기 때문에 이것이 더 빠를 것입니다.


4

이것은 어떤가요:

// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
  NodeList.prototype.filter = Array.prototype.filter;
}

// Use it like you'd expect:
const noClasses = document
  .querySelectorAll('div')
  .filter(div => div.classList.length === 0)

NodeList.forEach ( 'Polyfill'아래) 에 대한 MDN 문서 에서 언급 한 것과 동일한 접근 방식 이며 IE11 , Edge, Chrome 및 FF에서 작동합니다.


약간의 경고, 이제 nodeList.filter는 노드 목록 대신 배열을 제공합니다. 문제가되지 않습니다,하지만 쉽게 ^^ 잊지
hanshenrik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.