[javascript] 자식 노드를 얻는 가장 좋은 방법

JavaScript는 모든 요소에서 첫 번째 자식 요소를 가져 오는 다양한 방법을 제공하지만 궁금합니다. 가장 좋은 것은, 브라우저와 호환 가능하고, 가장 빠르고, 포괄적이며 예측 가능한 동작입니다. 별명으로 사용하는 메소드 / 속성 목록 :

var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]

이것은 두 경우 모두에 적용됩니다.

var child = elem.childNodes[0]; // or childNodes[1], see below

그것은 형태의 경우이거나 <div> 반복의 . 텍스트 요소가 발생할 수있는 경우 :

var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;

지금까지 내가 해결할 수로, firstChild로부터 NodeList를 사용 childNodes하고, firstElementChild용도를children . 나는 MDN 참조를 바탕으로이 가정을하고있다 :

childNode 요소 노드의 첫 번째 자식 요소에 대한 참조이거나 null 없는 경우입니다.

나는 속도면에서 차이가 있다면 아무것도 옆에 없을 것이라고 추측하고 있습니다. firstElementChild 효과적으로에 대한 참조입니다 children[0], 그리고 children객체 어쨌든 이미 메모리에.

나를 던지는 것은 childNodes물건입니다. 테이블 요소에서 양식을 살펴보기 위해 사용했습니다. children모든 양식 요소를 나열 하지만 childNodesHTML 코드의 공백을 포함하는 것으로 보입니다.

console.log(elem.childNodes[0]);
console.log(elem.firstChild);

두 로그 <TextNode textContent="\n ">

console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);

모든 로그 <input type="text"> . 어떻게 오세요? 한 객체가 “원시”HTML 코드를 사용하여 작업 할 수 있지만 다른 객체는 DOM을 사용하지만 childNodes요소는 두 레벨에서 모두 작동하는 것으로 보입니다.

내 초기 질문으로 돌아가려면 내 추측은 다음과 같습니다. 가장 포괄적 인 객체를 원한다면 childNodes 갈 길입니다.하지만 포괄적이기 때문에 원하는 요소를 반환하는 측면에서 가장 예측하기 쉽지 않을 수 있습니다. 주어진 순간에 기대하십시오. 이 경우 크로스 브라우저 지원도 문제가 될 수 있지만 내가 틀릴 수 있습니다.

누구나 가까이에있는 물건들 사이의 구별을 분명히 할 수 있습니까? 무시할만한 속도 차이가 있다면, 알고 싶습니다. 내가이 모든 것을 잘못 본다면, 저에게 교육을 주시기 바랍니다.


추신 : 제발, 제발, JavaScript를 좋아합니다. 예, 이런 종류의 일을 처리하고 싶습니다. “jQuery가이 문제를 해결합니다”와 같은 답변은 내가 찾는 것이 아니므로 아니요 꼬리표.



답변

당신이 그것을 너무 생각하고있는 것 같습니다. childNodes와 사이의 차이를 관찰했습니다. 공백으로 만 구성된 텍스트 노드를 포함하여 모든 노드 childrenchildNodes포함되어 있습니다.children 요소 만 자식 노드의 모음입니다. 그게 전부입니다.

알고 있어야 할 몇 가지 문제가 있지만 두 컬렉션에 대해 예측할 수있는 것은 없습니다.

  • IE <= 8은 공백 전용 텍스트 노드를 포함하지 않지만 childNodes다른 브라우저는 포함합니다
  • IE <= 8에는 주석 노드가 포함되어 children있지만 다른 브라우저에는 요소 만 있습니다.

children, firstElementChild친구는 편의상 요소로 제한되는 DOM에 대한 필터링 된보기를 제공합니다.


답변

firstElementChild는 IE <9에서 사용할 수 없습니다 (firstChild 만 해당)

IE <9에서는 MS DOM (IE <9)이 빈 텍스트 노드를 저장하지 않기 때문에 firstChild는 firstElementChild입니다. 그러나 다른 브라우저에서 그렇게하면 빈 텍스트 노드가 반환됩니다 …

내 솔루션


child=(elem.firstElementChild||elem.firstChild)

이것은 IE <9에서도 첫 번째 자식을 줄 것입니다.


답변

크로스 브라우저 방법은을 사용 childNodes하여 ELEMENT_NODE 를 사용 하여 NodeList모든 노드의 배열을 만드는 것 입니다.nodeType

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    var childNodes = element.childNodes,
        children = [],
        i = childNodes.length;

    while (i--) {
        if (childNodes[i].nodeType == 1) {
            children.unshift(childNodes[i]);
        }
    }

    return children;
}

http://jsfiddle.net/s4kxnahu/

lodash 와 같은 유틸리티 라이브러리를 사용하는 경우 특히 쉽습니다 .

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    return _.where(element.childNodes, {nodeType: 1});
}

미래:

의사 클래스 querySelectorAll와 함께 사용할 수 있습니다 :scope(선택기의 참조 점 인 요소와 일치).

parentElement.querySelectorAll(':scope > *');

작성 당시에는 Chrome, Firefox 및 Safari에서 :scope지원 됩니다.


답변

다른 답변에 덧붙여서, 특히 <svg>요소를 다룰 때 특히 주목할만한 차이점이 있습니다 .

나는 모두를 사용하고 있습니다 .childNodes.children및 작업 선호 HTMLCollection에 의해 전달 .children게터.

그러나 오늘은에서 사용할 때 IE / Edge에 문제가 발생 .children했습니다 <svg>. .children기본 HTML 요소에서는 IE에서 지원 되지만 문서 / 문서 조각 또는 SVG 요소 에서는 지원되지 않습니다 .

나를 위해, .childNodes[n]걱정할 텍스트 노드가 없기 때문에 필요한 요소를 간단히 잡을 수있었습니다 . 동일한 작업을 수행 할 수 있지만 위에서 언급 한 것처럼 예기치 않은 요소가 발생할 수 있습니다.

이것이 .children현대의 IE에서 js의 다른 곳에서 작동하고 문서 또는 SVG 요소에서 실패 하는 이유를 알아 내려고 노력하는 누군가에게 도움이 되기를 바랍니다.


답변

이봐, 당신은 공백이 당신을 바보 못하게합니다. 콘솔 브라우저에서 이것을 테스트하십시오. 기본 자바 스크립트를 사용하십시오. 다음은 동일한 클래스를 가진 두 개의 ‘ul’세트가있는 예입니다. 공백을 피하기 위해 ‘ul’목록을 모두 한 줄로 가질 필요는 없습니다. 공백을 뛰어 넘기 위해 배열 수를 사용하십시오.

js 바이올린 링크로 공백 querySelector()childNodes[]피하는 방법 : https://jsfiddle.net/aparadise/56njekdo/

var y = document.querySelector('.list');
var myNode = y.childNodes[11].style.backgroundColor='red';

<ul class="list">
    <li>8</li>
    <li>9</li>
    <li>100</li>
</ul>

<ul class="list">
    <li>ABC</li>
    <li>DEF</li>
    <li>XYZ</li>
</ul>


답변