Programing

document.querySelectorAll이 실제 배열이 아닌 StaticNodeList를 반환하는 이유는 무엇입니까?

lottogame 2020. 9. 10. 08:18
반응형

document.querySelectorAll이 실제 배열이 아닌 StaticNodeList를 반환하는 이유는 무엇입니까?


난 그냥 할 수 없어 그것은 버그 나 document.querySelectorAll(...).map(...)파이어 폭스 3.6도, 그리고 내가 교차 게시물을 줄이 블로그에서 SO 질문에 생각 그래서 난 여전히 답을 찾을 수 없습니다 :

http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/

어레이를 얻지 못하는 기술적 이유를 아는 사람이 있습니까? 아니면 StaticNodeList는 사용자가 사용할 수있는 것과 같은 방식으로 배열에서 상속하지 않는 이유 map, concat등?

(원하는 하나의 기능인 경우 다음과 같은 작업을 수행 할 수 있습니다 NodeList.prototype.map = Array.prototype.map;.하지만이 기능이 처음에 차단 된 이유는 무엇입니까?)


나는 그것이 W3C의 철학적 결정이라고 믿습니다. W3C DOM [spec]의 디자인은 DOM이 플랫폼과 언어 중립적 인 것을 의미 하므로 JavaScript 디자인과 매우 직교합니다 .

" getElementsByFoo()return an ordered NodeList"또는 " querySelectorAll()returns a StaticNodeList" 와 같은 결정 은 매우 의도적이므로 구현시 언어 종속 구현 (예 : .mapJavaScript 및 Ruby의 배열에서 사용할 수 있음)을 기반으로 반환 된 데이터 구조를 정렬하는 것에 대해 걱정할 필요 가 없습니다. C #의 목록에 없음 ).

W3C의 목표는 낮습니다. 그들은 모든 구현이 적어도 그것을 지원할 수 있다고 믿기 때문에 NodeLista에 unsigned long 유형readonly .length속성을 포함해야 한다고 말할 것 입니다 . 그러나 그들은 []위치 요소를 얻기 위해 인덱스 연산자가 오버로드되어야 한다고 명시 적으로 말하지는 않을 것입니다. 그들은 구현하고 getElementsByFoo()싶지만 연산자 오버로딩을 지원할 수없는 불쌍한 언어를 방해하고 싶지 않기 때문 입니다. 이것은 스펙의 많은 부분에 걸쳐 존재하는 널리 퍼진 철학입니다.

John Resig는 귀하 와 유사한 옵션 을 제시 했으며 다음과 같이 덧붙였습니다 .

내 주장은 NodeIteratorDOM과 같지 않은 것이 아니라 JavaScript와 같지 않다는 것입니다. JavaScript 언어에있는 기능을 활용하지 않고 최대한의 기능을 사용합니다.

나는 다소 공감한다. DOM이 JavaScript 기능을 염두에두고 특별히 작성 되었다면 사용하기가 훨씬 덜 어색하고 직관적 일 것입니다. 동시에 나는 W3C의 디자인 결정을 이해합니다.


ES2015 (ES6) 스프레드 연산자를 사용할 수 있습니다 .

[...document.querySelectorAll('div')]

StaticNodeList를 항목의 배열로 변환합니다.

다음은 사용 방법에 대한 예입니다.

[...document.querySelectorAll('div')].map(x => console.log(x.innerHTML))
<div>Text 1</div>
<div>Text 2</div>


배열 대신 노드 목록을 반환하는 이유를 모르겠습니다. 아마도 getElementsByTagName처럼 DOM을 업데이트 할 때 결과를 업데이트 할 것이기 때문입니다. 어쨌든 간단한 배열로 결과를 변환하는 매우 간단한 방법은 다음과 같습니다.

Array.prototype.slice.call(document.querySelectorAll(...));

다음을 수행 할 수 있습니다.

Array.prototype.slice.call(document.querySelectorAll(...)).map(...);

Crescent가 말한 것에 추가하기 위해,

원하는 함수 하나만 있으면 NodeList.prototype.map = Array.prototype.map과 같은 작업을 수행 할 수 있습니다.

이러지마! 작동이 보장되지는 않습니다.

JavaScript 또는 DOM / BOM 표준은 NodeList생성자 함수가 global / window속성 으로 존재 하거나에서 NodeList반환 된 속성 querySelectorAll이 상속되거나 프로토 타입이 쓰기 가능하거나 함수 Array.prototype.map가 실제로 NodeList에서 작동하도록 지정하지 않습니다.

NodeList는 '호스트 객체'가 될 수 있습니다 (IE 및 일부 이전 브라우저에서는 하나임). Array방법은 숫자 및 노출 자바 스크립트 '네이티브 객체에서 작동 할 수있는 것으로 정의 length특성을하지만,이 호스트 오브젝트에 대한 작업에 필요하지 않은 것 (그리고 IE에서, 그들은하지 않습니다).

DOM 목록에있는 모든 배열 메서드 (StaticNodeList뿐만 아니라 모두)를 얻지 못하는 것은 성가 시지만 신뢰할 수있는 방법이 없습니다. 모든 DOM 목록을 배열로 수동으로 변환해야합니다.

Array.fromList= function(list) {
    var array= new Array(list.length);
    for (var i= 0, n= list.length; i<n; i++)
        array[i]= list[i];
    return array;
};

Array.fromList(element.childNodes).forEach(function() {
    ...
});

다음과 같이 간단히 할 수 있다고 생각합니다.

Array.prototype.map.call(document.querySelectorAll(...), function(...){...});

그것은 나에게 완벽하게 작동합니다.


이것은 여기에서 다른 사람들이 제안한 다른 가능성의 범위에 추가하고 싶었던 옵션입니다. 이는 지적 재미만을위한 것이며 권장하지 않습니다 .


단지에 대한 재미 그것의, 여기에 "힘"에 방법 querySelectorAll당신에게 무릎을 꿇고 활하려면 :

Element.prototype.querySelectorAll = (function(QSA){
    return function(){
        return [...QSA.call(this, arguments[0])]
    }
})(Element.prototype.querySelectorAll);

이제 그 기능을 모두 밟아 누가 보스인지 보여주는 것이 기분이 좋습니다. 이제 더 나은 것이 무엇인지 모르겠습니다. 완전히 새로운 명명 된 함수 래퍼를 만든 다음 모든 코드에서 이상한 이름 (대부분의 jQuery 스타일)을 사용하거나 위와 같은 함수를 한 번 재정 의하여 나머지 코드는 계속 사용할 수 있습니다. 원래 DOM 메서드 이름을 사용합니다 querySelectorAll.

  • 이러한 접근 방식은 하위 방법의 사용 가능성을 제거합니다.

솔직히 당신이 [당신이 무엇을 알고 있는지]주지 않는 한, 나는 이것을 어떤 식으로도 추천하지 않을 것입니다.

참고URL : https://stackoverflow.com/questions/2600343/why-does-document-queryselectorall-return-a-staticnodelist-rather-than-a-real-ar

반응형