2008-07-10

NodeList型を知る

element.childNodesが返すやつ。こんなコードで知った。

var nodes = elem.childNodes;
for (var i=0; i<nodes.length; i++)
    nodes[i].parentNode.removeChild(nodes[i]);

上のコードはエラーになるわけだけど、これはelem.childNodesの返す値を配列ノリで扱っているため。 実際に返ってくるのはこんな定義の値。(引用元

interface NodeList {
  Node   item; // 0から始まる配列の添え字みたいの。
  readonly attribute unsigned long   length;  // NodeListの長さ。読み取り専用。
};

NodeListの性質で、最初に掲示したようなやり方でitemを削除するとNodeList自体が縮まることになる (最初、 [elem, elem, elem, elem, elem] だったのが、 [elem, elem, elem, elem] となる)。 これを配列の感覚で扱うと、最初はnodes[4] でアクセスできたものが、削除後にアクセスするとundefinedを返す。

これに対処するやり方はいくつかあって、

// elem.firstChildをあるだけ削除
while (elem.firstChild) {
    elem.removeChild(elem.firstChild)
}


// elem.lastChildをあるだけ削除
while (elem.lastChild) {
    elem.removeChild(elem.lastChild)
}


// ダイレクトに
elem.innerHTML = "";

ただ、これだと「ある条件」を満たすエレメントだけを削除したい場合にどうしようもないので、

// 愚直に
var nodes = elem.childNodes;
for (var i=0, target=[]; i<nodes.length; i++)
    if ( 削除条件 ) remove.push(nodes[i]);
for (var i=0; i<target.length; i++)
    elem.removeChild(target[i]);


// ダイレクトに
elem.innerHTML = elem.innerHTML.replace(/削除条件/, "");
という風にすればOK。

というようなことを今日知りました。

Posted at 02:23 in | WriteBacks (0) | Edit