2011-03-31 9 views
34

NodeList가 어떤 객체인지 알 수 있습니다. 배열과 같은 객체이고 괄호 표기법을 통해 액세스 할 수 있다고 읽었습니다 (예 : var a = someNode.childNode[0];). 우리가 객체의 속성에만 접근 할 수 있고, 우리가 가질 수 없다는 것을 알고 있기 때문에 어떻게 가능합니까?javascript의 NodeList 객체

+0

친절하고 청초한 질문 :) – Mahi

답변

8

NodeLists는 "live"입니다. 즉, 문서 구조가 변경 될 때 업데이트됩니다. 그들은 가장 정확한 정보를 항상 최신 상태로 유지합니다. 실제로 모든 NodeList 객체는 액세스 할 때마다 DOM에 대해 실행되는 쿼리입니다.

는 NodeList를을 반복 할 때마다, 그 변수에 반복자를 비교 한 후 길이가 두 번째 변수를 초기화하는 것이 가장 좋습니다 :

var divs = document.getElementsByTagName("div"); 

for (var i=0, lens=divs.length; i < len; i++){ 
    var div = document.createElement("div"); 
    document.body.appendChild(div); 
} 

NodeList의이 같은 구조 배열이지만 실제로는 아니다 배열. 대괄호 표기법을 사용하여 배열 값에 액세스 할 수 있습니다.

+0

방금 ​​읽은 책에 제가 쓴 것이 있습니다. 배열과 같은 의미는 할 수 없습니다. EcmaScript는 이와 같은 것을 지정하지 않습니다. 나는 그것이 구현 기술이라고 생각한다. – ppoliani

+0

ECMA의 DOM 사양이 아닙니다. 배열 (대괄호 표기법)처럼 반복 할 수 있지만 push(), splice() 또는 reverse()와 같은 Array 메서드를 사용하여 조작 할 수는 없습니다. –

+0

즉, 브라우저 수준 코드 (예 : C++)로 실행됩니까? – ppoliani

9

NodeList는 핵심 Javascript 객체가 아니며 브라우저와 DOM을 통해 제공됩니다. 동적 또는 라이브 객체에 대한 인터페이스를 반환하는 함수를 생각해보십시오. forEach()는 사용할 수 없지만이를 실제 배열로 변환하여 예를 들어 다음과 같은 스냅 샷을 만들 수 있습니다.

// turns nodelist into an array to enable forEach 
function toArray(list) { 
    var i, array = []; 
    for (i=0; i<list.length;i++) {array[i] = list[i];} 
    return array; 
} 

세부 사항 : http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-536297177

+0

글쎄, 나는 C++과 같은 언어로 구현되어 있다고 생각한다. 그렇더라도 JavaScript 코드와 어떻게 통신합니까? – ppoliani

+0

@ user512783 : 브라우저와 자바 스크립트 엔진에 따라 다릅니다. 왜 이걸 알고 싶니? – Martijn

+0

나는 DOM API가 EcmaScript로 쓰여졌는지 알아보기를 원했지만, 이해할 수있는 것은 아니다. – ppoliani

37

NodeList호스트 객체이며, 기본 자바 스크립트 객체에 적용되는 일반적인 규칙이 적용되지 않습니다. 따라서 length 속성과 대괄호 속성 액세스 구문을 통한 해당 멤버에 대한 액세스로 구성된 문서화 된 API를 고수해야합니다. 당신은 노드 목록의 구성원의 스냅 샷을 포함하는 Array 만들려면이 API를 사용할 수 있습니다

var nodeList = document.getElementsByTagName("div"); 
var nodeArray = []; 
for (var i = 0; i < nodeList.length; ++i) { 
    nodeArray[i] = nodeList[i]; 
} 
+2

이렇게하면 nodeList가 forin 루프에 의해 트래버스 될 수 없다는 의미입니까? – Triztian

+1

@ 트리즈티언 : 실제로 그렇습니다. 적어도, 그것이 작동한다는 보장은 없으며, IE에서는 그렇지 않다고 생각합니다. –

+1

Google 크롬에서도 작동하지 않습니다. length 속성을 사용하고 요소가 배열 인 것처럼 요소에 액세스해야합니다. – Triztian

8

자바 스크립트 알코올처럼, 그것은 강요 할 수

var links = document.getElementsByTagName('a'); 
Array.prototype.slice.call(links).forEach(function(anchor, index, arr) { 
    anchor.addEventListener('click', onClickFN, false); 
}); 
+0

... 또는 단지'Array.prototype.forEach.call (links, function() {})';) – yckart

+0

또는'[] .slice.call' – Mahi

37

NodeListDOM elements의 모음입니다. 그것은 배열과 같습니다 (그러나 그렇지 않습니다). 이를 사용하려면 일반 JavaScript 배열로 변환해야합니다. 다음 스 니펫을 통해 작업을 완료 할 수 있습니다.

const nodeList = document.getElementsByClassName('.yourClass'), 
     nodeArray = [].slice.call(nodeList); 
+0

'[] .slice.call (nodeList)'작품 만 있으면됩니다. 나를위한 매력처럼. 왜/어떻게 작동하는지 알고 싶습니다. – Lounge9

+4

기본적으로 javascript는 빈 배열의 contenxt를 call 메소드를 사용하여 nodeList로 설정하기 때문에 nodelist를 배열로 처리합니다. 그런 다음 단순히 slice 메소드가 자체의 정확한 사본을 리턴합니다 (인수없이 사용 된 경우). 이 질문에 대한 답변을 : ( – brielov

+0

훌륭하게, 다시 고마워! – Lounge9

6

노드 목록은 종종 필터가있는 노드 반복자로 구현됩니다. 즉 길이가 같은 속성을 얻는 것은 O(n)이며 길이를 다시 확인하여 목록을 반복하는 것은 O (n^2)가됩니다.

var paragraphs = document.getElementsByTagName('p'); 
for (var i = 0; i < paragraphs.length; i++) { 
    doSomething(paragraphs[i]); 
} 

대신이 작업을 수행하는 것이 좋습니다 :

var paragraphs = document.getElementsByTagName('p'); 
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) { 
    doSomething(paragraph); 
} 

이 한 배열이 부울 거짓으로 취급하는 일을 포함하지 않는 모든 컬렉션과 배열에 적합합니다.

childNodes를 반복하는 경우 firstChild 및 nextSibling 속성을 사용할 수도 있습니다.

var parentNode = document.getElementById('foo'); 
for (var child = parentNode.firstChild; child; child = child.nextSibling) { 
    doSomething(child); 
} 
+0

이 대답은 O (n)과 O (n^2)가 무엇인지에 대한 설명으로부터 이점을 얻을 수 있습니다. – TylerH

+2

@TylerH 위키 백과 링크 추가 –

+1

Ehm, 단지 * 부울 false * 값은 루프를 깨뜨릴 것이고, 모든 * falsey * ('undefined','null','0' 등) 값은 ... – yckart