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

2008-06-01

[CodeReading][jQuery]

undefinedという名前のグローバル変数を定義している。初期化はしていないので変数の内容はundefined。 「fuga === undefined」みたいに使う。「typeof hage == 'undefined'」よりも早いみたい。

+new Dateで、1970/01/01 00:00:00からのミリ秒表現を取得。

Posted at 06:14 in | WriteBacks (0) | Edit

2008-05-31

[CodeReading][Datejs]変数宣言の書き方が気に入った。

var hoge = "hoge",
    foo  = "foo",
    bar  = "bar";
みたいに書いてるところがあって、
var hoge = "hoge";
var foo  = "foo";
var bar  = "bar";
より見やすい気がした。

Date.nowを定義しているので注意。(Firefoxだけ?)

Dateオブジェクトの複製をつくるcloneメソッドはgetTime()を使用。toString()は文字列の解析で遅くなるので使わない。

Posted at 17:03 in | WriteBacks (0) | Edit

2008-05-29

Date.parse('2008-05-29')

javascript:alert(Date.parse('2008-05-29'))
  • Opera - 1970年1月1日 00:00:00からのミリ秒数を返す。
  • Firefox - NaNを返す。
  • IE - NaNを返す。

へー。

Posted at 21:19 in | WriteBacks (0) | Edit

[備忘] setIntervalとsetTimeoutの使い分けがわからない

わかっていないことの備忘録。 JavaScriptでタイマーを使ったコード(アニメーションとか)を書く時のはなし。

setIntervalを終了条件つきで書くか、

var tid = setInterval(function() {
  // 処理
  if (is_end) clearInterval(tid); /* 終了条件 */
}, milliseconds);

必要な回数だけsetTimeoutを呼ぶか。

for (var i=1; i<=times; i++) {
  setTimeout(function() {
    // 処理
  }, milliseconds * i);
}

「// 処理」に当たる部分を1回しか実行しないなら、タイマーの破棄が必要ない分だけsetTimeoutの方がいい気がする。でも、「// 処理」を複数回実行するとなると、どういう基準で使い分けるのがいいんやろか?

今のところ、事前に「// 処理」の回数がわかっている場合にsetTimeout、それ以外の場合はsetIntervalという風に使い分けているけど、setTimeoutのforループが千回とか超えるとちょっと不安になる。

setTimeoutとsetIntervalの違いがよくわかってない。→調べて追記しよう。

追記

お、ココにsetTimeout/setIntervalの違いが。

JavaScriptはシングルスレッドなので、非同期処理(イベントハンドラとか、タイマーによる遅延処理)はキューを使って処理しているから、setTimeout/setIntervalのコールバックが遅れることもあるよ。的なことが書いてあって、

  • setTimeoutは、指定したミリ秒後にコールバックを実行。
  • setIntervalは、指定したミリ秒間隔でコールバックを実行。

とある。

うーん、おもしろいけど、何か違う。setTimeoutで指定したコールバックが実行キューに入るのはわかるけど、キューに入れるタイミングをどうやって管理されているのかが知りたい。それがわかれば、「forループ + setTimeout」と「setInterval + 終了条件」の違いがわかるよなあ。

Posted at 00:24 in | WriteBacks (0) | Edit