用于Javascript的Ruby样式before()和after()过滤器

时间:2013-07-18 18:56:20

标签: javascript

有没有办法在Javascript中添加函数调用之前和之后?我有这样的事情:

var A = {

  a1: function () {

  },
};

var B = {

  b1: function () {

  }
};

A.a1();
B.b1();
//so on .. 

我需要在每种方法之前和之后发生一些事情。我可以在函数之前和之后创建它们并分别调用它们,但我必须经常在代码中执行此操作并且不想重复自己。

更新: 在红宝石

before_filter :some_function
after_filter  :some_other_function

将在该类中的每个函数调用之前执行some_function,并在每次函数调用之后执行some_other_function。此外,在Rails的Application Controller中也找不到。

4 个答案:

答案 0 :(得分:2)

您可以编写一个枚举对象字段并将其函数包装在新对象中的函数:

function addBefore(obj, func) {
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop) && typeof obj[prop] === 'function') {
            (function () {
                var oldFunc = obj[prop];
                obj[prop] = function () {
                    func.apply(obj, arguments);
                    return oldFunc.apply(obj, arguments);               
                }
            }());
        }
    }
}
var A = {

  a1: function (a, b) {
    alert('A.a1');
    return a + b;
  },
  a2: function (a, b) {
    alert('A.a2');
    return a + b;
  }
};
addBefore(A, function (a, b) {
    alert('before ' + a + ', ' + b);
});
A.a1(1, 2);
A.a2(3, 4);

以类似的方式你可以编写一个函数addAfter,只需将两个调用切换到apply()函数。

答案 1 :(得分:1)

尝试此操作来更改对象中的所有函数:

var beforeAll = function(o, f) {
  for (var p in o) {
    if (o.hasOwnProperty(p) && typeof(o[p]) === "function") {
      o[p] = (function(oldF) { 
        return function() {
          f.apply(this, arguments);
          return oldF.apply(this, arguments);
        };
      }(o[p]));
    }
  }
};

var A = {
  func1: function() {console.log('func1')},
  func2: function() {console.log('func2')}
};

beforeAll(A, function() {console.log('before')});

A.func1();
A.func2();

(您可以为afterAll创建类似的一个。)

小提琴here

请注意,您需要捕获循环中的旧函数才能正确绑定它。更多信息here

答案 2 :(得分:0)

如果您保存原始功能并在之后(或之前)之后调用它,请执行以下操作:

var A = {

  a1: function () {

  }
};

var orginal = A.a1
A.a1 = function(){
  // the before code
  orginal.apply(this, arguments)
}
所有道具的

for(prop in A){
  var orginal = prop
  A[prop] = function(){
    //before code
    orginal.apply(this, arguments)
  }
}

我将类型检查作为读者的练习:)

答案 3 :(得分:0)

在javascript中,惯例是对这类事情使用回调。因此,如果您只想一个接一个地触发一个函数,它将看起来像这样:

var a1 = function(callback){
  console.log('doing function things la la');
  callback();
}

现在,当你调用a1函数时,你会做这样的事情:

a1(function(){
  console.log('this is only printed at the end!');
});

我想,你可以在函数中添加另一个第二个参数,这个函数在我猜之前更像是一个调用,但你不会经常看到它。

如果你在谈论在没有回调的大量方法之前运行某个函数,我认为最好的方法就是用一个接受你的主要函数作为回调的函数来包装它们,像这样:

var a1 = function(){ console.log('a1'); }
var a2 = function(){ console.log('a2'); }
var a3 = function(){ console.log('a3'); }
var a4 = function(){ console.log('a4'); } 

var before_filter = function(callback){
  console.log('doing some stuff before whoo!');
  callback();
}

[a1, a2, a3, a4].map(function(fn){
  before_filter(fn);
});

让我知道这不是你所追求的,我很乐意添加更多选项 - 有很多可能的方法来处理这个问题,它只取决于你究竟在寻找什么。由于before_filter s本身并没有内置到javascript中,因此很难使它像ruby一样干净,但是看看那里的最后一个例子,你可以看到很容易让它非常接近。还有一个类似于最后一个的替代方案:

var a1 = function(){ console.log('a1'); }
var a2 = function(){ console.log('a2'); }
var a3 = function(){ console.log('a3'); }
var a4 = function(){ console.log('a4'); } 
var before = function(){ console.log('doing before stuff'); }

var before_filter = function(before_fn, fn){
  before_fn();
  fn();
}

[a1, a2, a3, a4].map(function(fn){
  before_filter(before, fn);
});