2012年6月28日木曜日

JavaScriptのsetTimeout()で指定する関数の引数に値を渡したいとき

JavaScriptで定期的に処理を行わせたいときに、setTimeout()またはsetInterval()を使う事があります。
// 1秒間隔でdoSomething()を実行
setInterval(doSomething, 1000);
その第1引数には処理を定義した関数を与えるのですが、その関数の引数に値を渡したい時は以下のように呼びます。
setInterval(doSomething, 1000, value);
setInterval(doSomething, 1000, value1, value2, value3);
あるいは
setInterval("doSomething('" + value + "')", 1000);
文字列で渡すパターンは途中にシングルクォートを入れるのがミソらしいんだが、具体的な理由は不明(´・ω・`)
ちなみに、MOZILLA DEVELOPER NETWORKのwindow.setTimeoutwindow.setIntervalに関数の説明が書いてあります。ECMA262には書いていませんでした。ということは、ECMAで定めた関数じゃないんですかね。

その他参考サイト:
setTimeoutで引数が入った関数を呼ぶ

JavaScriptで小数の表示

暇つぶしにJavaScriptでストップウォッチを作っていたのだが、0.1秒とか11.5秒とかはそのまま表示されるのに、10.0秒みたく小数点以下が全部0だと、それらが切り捨てられて10と表示されてしまう。10.0と表示したい時は以下のメソッドを使えばおk

var val = 10;
val.toFixed(1);  // 10.0

toFixed()は小数点表示の文字列値に変換するメソッドです。引数は、小数点以下の桁数を表します。

ちなみに、JavaScriptの数値型(Numberオブジェクト)は64ビット浮動小数点数です。なので数値計算は(たとえ整数のつもりでも)内部では全て実数として扱われます。小数点以下が全て0のときに文字列にすると小数点以下が切り捨てられて、整数に見えるとのこと。ちなみに、ビット演算の時は内部では32ビット整数で計算されるみたい。

参考サイト:
javascript - には整数はない

2012年6月23日土曜日

JavaScriptのArgumentsオブジェクトを配列に変換

JavaScriptには、関数の引数情報を表すArugmentsオブジェクト、DOM APIのgetElementsByTagName()が返すNodeListオブジェクトのように、配列だけど配列でないオブジェクト(以下、配列風オブジェクトと呼ぶ)が存在する。

配列ではないので、単純に配列(Arrayオブジェクト)のメソッドをそのまま呼ぶ事はできない。call()やapply()を用いて呼べばOKなメソッドもあるが、場合によっては配列に変換しないとダメとか、むしろ変換しちゃったほうが何かと都合がいいとかあるだろう。

変換方法は以下のコードを1行実行するだけで良い。
var array = Array.prototype.slice.apply(arguments);

Arrayオブジェクトのslice(start, end)は、配列から指定したインデックスの要素を抜き出した新しい配列を返す(インデックスを指定しなかったら中身が全く同じの新しい配列を返す)メソッドで、このメソッドを使う事で配列風オブジェクトから配列が返ってくる。

そもそも、なんでこいつを使うと本物の配列が返るのかというと、配列風オブジェクトの特徴が

  • lengthを持つ
  • 数値プロパティを持つ(プロパティ名が数値なので、arguments[1]とやると値を取得できる)

であり、slice()が以下のような実装になっているからだと思う。
var slice = function(start, end) {
 var newArr = [];
 var i = start || 0;
 end = end || this.length;

 for (; i < end; i++) {
  newArr.push(this[i]);
 }

 return newArr;
}

↑だいぶざっくりと書いているので気をつけてください(startの値が負数だとか、endの値が配列の長さ以上だとか考慮してないっす)。メソッドになっていないのも勘弁してください。
ポイントはthis(apply(), call()で呼べばthisは配列風オブジェクト)とpush()のところで数値でプロパティ値を取得してるところかな。