javascriptでAspect3

実用性を考えた結果、beforeやafterにはoriginalを渡す方が便利だし、aroundも欲しいということで↓のようになった。

var wrap = function(original,before,after,around){
  var func = function(){
    if(before){
      before.apply(this,[original,arguments]);
    }
    var result;
    if(around){
      result = around.apply(this,[original,arguments]);
    } else {
      result = original.apply(this,arguments);
    }
    if(after){
      after.apply(this,[original,arguments,result]);
    }
    return result;
  };
  func.__proto__ = original;//__proto__チェーンを処理
  //func.name = original.name;//nameの書き換えが出来ない!ちょっと不服。
  func.toString = function() {
    return func.__proto__.toString();
  };//AspectのtoStringは全部同じなので隠す。
  return func;
};

var obj = { _x:"X", getX:function(){return this._x;} };
alert(obj.getX());
// 乗っ取りの実行
obj.getX = wrap(obj.getX,
                function(original,args){
                  for(var i=0,str="";i<args.length;i++){
                    if(i!=0){str+=",";}
                    str += args[i].toString();
                  }
                  alert("Arguments are ("+str+")");
                },
                function(original,args,result){
                  alert("Result is "+result);
                });
alert(obj.getX());