◆ transition アニメーションとか?

JavaScript

JavaScriptは 他の言語みたいに 「main 関数を実行して そこからいろいろな関数を実行して最終的に main関数が終わったら プログラムはそこで終了 」 という言語じゃありません

PHPみたいな main関数がない言語もありますが それはスクリプトファイル全体が main関数の中に書かれてると考えれば一緒なはずです

JavaScriptではプログラムはずっと動いていて 何か(イベント)があると設定された関数を呼び出すというブラウザで使われるのに特化した仕組みになってます

main関数にあたるスクリプトの上から下まで全部が終わると することできるまで待ってます
何かがクリックされたのを見つけると それに応じた関数を実行します

非同期実行

非同期関数が実行されると あとでやる に登録しておいて今やってる処理が全部終わってヒマになると あとでやる に登録しておいたのを順にやり始めます

setTimeout では あとでやる に登録するときに やるのは今から指定された時間以降 と設定できます
setTimeout(fn, 1000*60*60) なら やるのは今から1時間後以降 と登録されます

なので仕様を調べると 指定されたミリ秒以降に実行されるけどピッタリその時刻に実行されるわけではない と書かれてるんです
1時間後に ちょうど他の関数を実行していればそれが終わらないと setTimeout で設定した関数は実行できずに今の作業が終わるまで待つことになります

setTimeout

文章だけだとわかりづらいので適当に実行してみます
function a(){
console.log("a-start", new Date().toLocaleTimeString())
setTimeout(b, 3000)
x()
setTimeout(y, 1000)
console.log("a-end", new Date().toLocaleTimeString())
}
function b(){
console.log("b-start", new Date().toLocaleTimeString())
c()
console.log("b-end", new Date().toLocaleTimeString())
}
function c(){
console.log("c-start", new Date().toLocaleTimeString())
d()
console.log("c-end", new Date().toLocaleTimeString())
}
function d(){
console.log("d-start", new Date().toLocaleTimeString())
setTimeout(e, 0)
console.log("d-end", new Date().toLocaleTimeString())
}
function e(){
console.log("e-start", new Date().toLocaleTimeString())
console.log("e-end", new Date().toLocaleTimeString())
}
function x(){
console.log("x-start", new Date().toLocaleTimeString())
console.log("x-end", new Date().toLocaleTimeString())
}
function y(){
console.log("y-start", new Date().toLocaleTimeString())
console.log("y-end", new Date().toLocaleTimeString())
}

a()

このコードをコンソールで実行します
a-start 14:47:51
x-start 14:47:51
x-end 14:47:51
a-end 14:47:51
undefined
y-start 14:47:53
y-end 14:47:53
b-start 14:47:55
c-start 14:47:55
d-start 14:47:55
d-end 14:47:55
c-end 14:47:55
b-end 14:47:55
e-start 14:47:56
e-end 14:47:56

a では b, x, y の3つの関数を呼び出しますが x 以外は非同期です
なので a の次には x が実行されて 一旦コードの評価が終わるので undefined a() の返り値として表示されています

a の中では後から実行するように設定されていますが 開始する時刻早い y が先に実行されます
その後で b が実行されます
setTimeoutで0ミリ秒が指定された eb が終わってから実行されます
55秒から56秒に変わってますが 待ち時間は1秒もないです

setTimeout(fn, 0)

第二引数に0を指定するのは省略したのと一緒で 今の処理が終わり次第即実行になります

これっていつ使うんでしょう?
いつ起きるかわからないことが起きたことの判別とかでしょうか?

何かが変わるのを待つため?

例えば ロード完了したら処理したいのを待つため
JavaScriptでは waitsleepはないですし シングルスレッドなのでwhile無限ループでフラグをずっと確認していても while文の中身の処理以外でフラグが書き換わることはないです

setTimeout で確認すると 一旦処理が終わるので 別の処理が間に入ってきて フラグ書き換えが起きることがありえます

ですが

ロード完了ならたいてい onload のような完了後のイベントがありますし それにリスナをつけるのが普通です
もし イベントがなくても自分が処理を書いてるわけですのでJSONPみたいに処理後に特定の関数を呼ぶようにしておけばいいはず

何かの理由で setTimeout でするにしても 0ほどこまめにチェックする必要はないと思います
さすがに5000くらいまで大きくすると 余分な待ち時間が増えてしまいますが 50とか100くらいなら気にならない程度でしょうし 必要以上に短い間隔でのチェックを繰り返さないので 0よりはいいと思います


そうなると やっぱり 0を使う意味って無い??

アニメーションのため

もう少し考えてみると CSSと組み合わせたデザインで使いみちがありそうです

transition を付けておいた要素を 非表示から表示にして その後にプロパティを変えることで アニメーションさせたいとします
<div style="display:none;height:100px;transition:height 3s linear 0s"></div>
の要素をJavaScriptでこう操作してみます
elem.style.display = "block"
elem.style.height = "400px"

transition があるのでアニメーションしてくれそうです

が実際はやってくれません


ブラウザの処理で DOM更新や プロパティ変更などは 一瞬で終わるかるーい処理です
ですが 描画部分はすごく重い処理です
ゲームでも一緒ですね

なので DOMやCSSに変更があっても毎回表示は更新しません
JavaScriptの1つの処理が終わって待機状態になると描画されます
こうして高速化がされているんです

ですが そのせいで display block にしてもまだ非表示です
なので 400px にしても見えていないのでアニメーションはしないでいきなり 400px にしてしまいます
そのあとで表示が行われるのでアニメーションなしで高さ 400px で表示されます


では どうやるかですが ここで setTimeout 0が関わってきます
ここでいう JavaScriptの1つの処理というのは setTimeout の0秒で設定されたすぐにやるものが あとでやる のリストにあっても別々になります
最初のいわゆるメイン部分と あとでやる の1つ1つが単位になっています
elem.style.display = "block"
setTimeout(function(){elem.style.height = "400px"},0)

こうすればOKです
いったん処理を分けたいだけで待つ必要はないので 0 を設定するのがふさわしい方法だと思います

サンプル↓
http://var.blog.jp/s/setTimeout-0.html