DateのgetTime省略と、Math.floorを使わない切捨て計算

ニコニコのJSを眺めていたら、おもしろいコードがあったのでメモする。


マイページで読み込まれるmy3.jsの236行目*1

var ts = new Date/1000|0;


まず、new Date/1000
getTime() を書かなくても、勝手にミリ秒にしてくれるとは知りませんでした。

>>> new Date/1000
1234567890.123

// 上と同じ
>>> (new Date).getTime()/1000
1234567890.123


掛け/割り/引き算は数値として扱われるけど、
足し算だと文字列(Date.toString()した値)として扱われるっぽい。

>>> new Date*1
1234567890123

>>> new Date/1
1234567890123

>>> new Date-0
1234567890123

>>> new Date+0
Sat Feb 14 2009 08:31:30 GMT+09000  // (new Date).toString() + 0  と同じ

なので、『(new Date).getTime() なんて長くて書きたくない!』
って人は足し算以外を使うとほんの少しだけスマートに書けるかも。


ただ、無駄な演算をしてるので、その辺も合わせて好みな気がする。
(※) 実行時間は、100万回まわしても誤差の範囲内(数十ms〜数百ms)くらいしか差がなかったです*2


個人的には、ミリ秒のまま使うならgetTime()と迷うけど、どうせ1000で割ったりするなら、
getTime()無しの方がコードが短くていい感じだと思う。

      • -

もう1つ、<少数> | 0
何が起きてるかというと、小数点以下切捨て。


普通なら Math.floor() を使っちゃうところですが、|0 でできるらしいです。
『|』はビットの論理和なので、|0 したところで、そのままの値が返ってきそうなものですが、
javascript論理和は不動小数点を整数に変換してから処理するようです*3
参考:ビット演算子 - 演算子 - JavaScript入門


つまり、整数に変換された時点で小数点以下が切捨てられ、
あとはそのままの値が返ってくるということだと思います。


ちなみに、実行時間的にも Math.floor より速そうです*4
マシンスペックとかブラウザにもよりそうなので、明言は避けときますが、
自分の環境だと、Math.floor() や parseInt() よりも明らかに『|0』の方が速かったです。


とは言っても、1回使う分にはまったく気にする必要はないですが。


計測に使ったコードは以下。

var s = (new Date).getTime();
for (var i=0; i<1000000; i++) {
    var val = 3.2|0;
    //var val = Math.floor(3.2);
    //var val = parseInt(3.2);
}
var e = (new Date).getTime();
alert(e-s);
      • -

長々と書いたけど、結局は

var ts = Math.floor((new Date).getTime()/1000);

これが、

var ts = new Date/1000|0;

こんな風に書けるんだー、すごい!短くてステキ! という話し。

*1:2009/11/17 時点

*2:Firefox3.5.5とIE8でしかみてないけど

*3:他の言語は知りません

*4:Firefoxだとそんなに差は無かったけど、IE8だと100万回まわして1〜2秒くらい違った