« Japanize - Opera9に対応しました | メイン | Firefox Developers Conference での質疑応答メモ »

2006年12月14日

setTimeout をオブジェクト指向にしてみる

 setTimeout と setInterval が window オブジェクトのプロパティなのは、それがブラウザの機能であって言語処理系自体の機能でないことを考えれば当然だと思います。しかし、それがゆえか、this が引き継げなかったり、IE では引数が渡せなかったりといった不便があります。どうせだったら、こうなっていたらよかったのにね、ということで、Function.prototype をイジってみました。すでにありそうなネタですが (苦笑)

Function.prototype.applyTimeout = function (ms, self, args) {
  var f = this;
  return setTimeout(
    function () {
      f.apply(self, args);
    },
    ms);
};

Function.prototype.callTimeout = function (ms, self) {
  return this.applyTimeout(
      ms,
      self,
      Array.prototype.slice.call(arguments, 2));
};

Function.prototype.applyInterval = function (ms, self, args) {
  var f = this;
  return setInterval(
    function () {
      f.apply(self, args);
    },
    ms);
};

Function.prototype.callInterval = function (ms, self) {
  return this.applyInterval(
      ms,
      self,
      Array.prototype.slice.call(arguments, 2));
};

 これを使えば、いちいちクロージャーを作らなくてよくなります。たとえば foo.bar(hoge) を 1000ms 後に setTimeout したい場合、

foo.bar.callTimeout(1000, foo, hoge);

と書くことができます。

foo.bar.applyTimeout(1000, foo, [ hoge ]); // これでも OK
foo.bar.callInterval(1000, foo, hoge); // setInterval 版
foo.bar.applyInterval(1000, foo, [ hoge ]); // setInterval & apply 版

投稿者 kazuho : 2006年12月14日 14:06 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

トラックバック

このエントリーのトラックバックURL:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/976

コメント

おおおおおお。なるほど!その発想はありませんでした!
やっぱりプロトタイプって素敵ですねえ。。。

あ。なんか、どうでもいいことなんですが。タイマーの id を return してみてはどうでしょう。

投稿者 amachang : 2006年12月14日 17:45

amachang さん、ありがとうございます。

id を return しないと使いものになりませんね。修正しました。

投稿者 kazuho : 2006年12月14日 20:53

イイ!

投稿者 komagata : 2006年12月15日 19:41

このままだとcallTimeout/callIntervalにてmsのみを渡したとき引数がおかしくなるので、
var args = Array.prototype.slice.call(arguments, 2);
としたほうがいいのではないでしょうか。

投稿者 nanto_vi : 2006年12月15日 20:22

nanto_vi さん、ありがとうございます。修正しました。

投稿者 kazuho : 2006年12月16日 17:19