Pot.override

{Object} Pot.override ({Object} object, {String|RegExp|Array} properties, {Array|Function} converters/overrider [, {Array|Function} converters/overrider])

Pot.js と PotLite.js で利用可能。

object の関数をオーバーライドします。

引数 object が持つ関数 properties を、関数 overrider でオーバーライドします。
引数 object は、オーバーライドしたい関数をもつ親オブジェクトを指定します。
引数 properties は、オーバーライドする関数名を文字列または正規表現で指定、 または複数の関数を対象とし、配列で指定します。
引数 overrider は、オーバーライドする関数を渡します。
引数 converters が渡されると、対象の関数のコードを converters 通りに置換します。
overrider もしくは converters が必須です。
overrider と converters の両方を指定することも可能です。

properties が正規表現または配列の場合、複数の関数をオーバーライドします。

overrider に渡される引数は以下の 4 つです。

function (inherits, args, self, prop) {}

  - inherits : {Function}  オリジナルの関数。
  - args     : {Arguments} オリジナルの引数。
  - self     : {Object}    オリジナルの関数の 'this'。
  - prop     : {String}    対象の関数名。

converters を指定する場合、置換パターンと結果文字列で構成された配列で渡します。
例えば、[/\breturn\b\s*([^;]+);/, 'throw $1;'] を指定すると
オーバーライドする関数は return する代わりに それを throw する動作になります。
複数のパターンを指定する場合は、上のようなペアを複数持つ配列を渡します。
converters と overrider の両方が指定された場合、 converters によるコード置換が適応された後に overrider によりオーバーライドされます。

また、converters で置換する際には コード内のコメントが除去されたり式が最適化されるかもしれません。
実行環境により差が出てしまうので、実行結果が意図した結果かどうか、注意してください。

関数がオーバーライドされた object が返ります。

// overrider のみ指定した例

var Hoge = {
  addHoge : function(value) {
    return value + 'hoge';
  }
};

debug(Hoge.addHoge('fugafuga')); // 'fugafugahoge'

override(Hoge, 'addHoge', function(inherits, args, self, prop) {

  // オリジナルの関数の引数の 0 番目の値
  var value = args[0];

  // 引数を 以下のように変更
  var modify = '{{Modified:' + value + '}}';

  // 元の引数を消す
  args[0] = '';

  // 先頭に追加してオリジナルの関数を呼び出す
  return modify + inherits(args);
});

var result = Hoge.addHoge('fugafuga');

debug(result); // '{{Modified:fugafuga}}hoge'
// converters を指定する例

var Numbers = {
  NAME   : 'Numbers',
  logAdd : function(a, b) {
    return this.NAME + ':' + (a + b);
  }
};

debug(Numbers.logAdd(1, 2)); // 'Numbers:3'

override(Numbers, 'logAdd', [[
  /\bthis\.NAME\b/, // this.NAME を "Result" に置換
  '"Result"'
], [
  /(["']):(['"])/,  // ':' を ' = ' に置換
  '$1 = $2'
], [
  /\ba\s*[+]\s*b\b/, // + を * に置換し最後に * 100 を追加
  '(a * b * 100)'
]]);

debug(Numbers.logAdd(1, 2)); // 'Result = 200'
// converters と overrider の両方を指定する例

var Numbers = {
  NAME   : 'Numbers',
  logAdd : function(a, b) {
    return this.NAME + ':' + (a + b);
  }
};

debug(Numbers.logAdd(1, 2)); // 'Numbers:3'

override(Numbers, 'logAdd', [

  // 「this.NAME + ':' +」 を 「"(*l_l)/"」 に置換

  /this\.NAME\s*[+]\s*([()])?\s*["']:['"]\s*[+]/,
  '"(*l_l)/"+$1'
], function(inherits, args, self, prop) {

  // 引数 a と b を取得
  var a = args[0], b = args[1];

  // 引数 a と b に 100 足して渡す
  return '{{' + inherits(a + 100, b + 100) + '}}';
});

debug(Numbers.logAdd(1, 2)); // '{{(*l_l)/203}}'