1

有没有办法在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 的应用程序控制器中也找不到。

4

4 回答 4

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() 函数。

于 2013-07-18T19:54:34.240 回答
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)。

在这里拉小提琴。

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

于 2013-07-19T23:07:36.260 回答
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)
  }
}

我将类型检查作为读者的驱魔:)

于 2013-07-18T19:52:59.740 回答
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);
});

如果这不是您想要的,请告诉我,我很乐意添加更多选项——有很多潜在的方法可以解决这个问题,这取决于您到底在寻找什么。由于 s 本身并没有内置到 javascript 中,因此很难让它像 ruby​​ 一样干净before_filter,但是查看最后一个示例,您会发现很容易让它非常接近。与上一个类似的另一种选择:

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);
});
于 2013-07-18T19:55:44.230 回答