IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

finally がマイブーム

皆様お久しぶりです

そろそろ、日記を書かないと「はてな市民権」を剥奪されそうなので、書いておきまつ><

最近

finally がマイブームです

どういうときに?

比較的に大規模な開発のとき(プロトタイプとかちゃんと使ってるとき)

どんなコードで?

こんなコード。 Fuga を継承した Hoge を作る場合とか

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {
  return Fuga.prototype.getValue.apply(this, arguments);
};

この return 〜 .apply(this, arguments) までは定型区みたいなもんなので、まず書いちゃいますね。
で、たとえば、
getValue に事前処理を入れたければ

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {

  // 事前処理
  this.value = 'hoge';

  return Fuga.prototype.getValue.apply(this, arguments);
};

こんな感じで書きます。
事後処理を入れたければ

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {

  // 事前処理
  this.value = 'hoge';

  var r = Fuga.prototype.getValue.apply(this, arguments);

  // 事後処理
  delete this.value;

  return r;
};

こんな感じですね。

でも、これだと

エラーが throw されたとき、事後処理が飛ばされるという危険性があったりしますね。
それに「var r」がめんどくさい感じです。

なので

最近はこんな感じで書くことが多いです。

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {
  // 事前処理
  this.value = 'hoge';
  try {
    return Fuga.prototype.getValue.apply(this, arguments);
  }
  finally {
    // 事後処理
    delete this.value;
  }
};

なんか、スッキリしませんか。
ただ、この方法だと返り値を使った処理が出来ないので、そういう場合は「var r」がいりますね。

ちょっと応用

最後に、この方法を使う典型的な例をあげておきます。

一時的に関数の意味を変える

継承元を書き換えずに、一時的に関数の意味を変える

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {
  this.getName = function() { return 'hoge' }; // 関数を一時的にオーバーライド
  try {
    return Fuga.prototype.getValue.apply(this, arguments); // この中では、オーバーライドされた関数を使う
  }
  finally {
    delete this.getName; // 関数を元に戻す。 delete しても、プロトタイプには残ってるので問題ない。
  }
};
メソッドの影響を調べる

これは、複雑なライブラリを使うときによく使います。

var Hoge = function() { /* ...(snip)... */ };
Hoge.prototype = new Fuga();

// メソッドのオーバーライド
Hoge.prototype.getValue = function() {
  try {
    return Fuga.prototype.getValue.apply(this, arguments);
  }
  finally {
    console.log(this); // getValue が this に与える影響を調べる
  }
};

ところで

「返り値」って変換したら、「返り血」になった。そんな金曜日。