回调作为对象属性

时间:2013-08-31 23:06:58

标签: javascript

我希望得到类似的功能:

function foo(before, after){

    before();

    setTimeout(function(){
         after();
    },100)
}

foo(function(){
    console.log('before');
}, function(){
    console.log('after');
});

返回对象而不是使用回调(伪代码)时:

var foo = function() {

     before();         

     setTimeout(function(){
         after();
     },100)

     return {
         before: before,
         after: after
     }
};

foo().before(function(){
    console.log('before');
});

foo().after(function(){
    console.log('after');
});

或者甚至

foo().before(function(){
    console.log('before');
}).after(function(){
    console.log('after');
});

这可能吗?

5 个答案:

答案 0 :(得分:4)

是的,您的函数可以使用beforeafter方法返回一个对象,该方法可以跟踪已设置的回调,当两者都设置时,它可以调用它们:

function foo() {

    var beforeFunc = null, afterFunc = null;

    function activate() {
        beforeFunc();
        window.setTimeout(afterFunc, 100);
    }

    var obj = {
        before: function(f) {
            beforeFunc = f;
            if (afterFunc != null) activate();
            return obj;
        },
        after: function(f) {
            afterFunc = f;
            if (beforeFunc != null) activate();
            return obj;
        }
    };

    return obj;

}

// As both callbacks need to be set, the order is not important
foo().after(function(){
    console.log('After');
}).before(function(){
    console.log('Before');
});

演示:http://jsfiddle.net/4HypB/

答案 1 :(得分:2)

几乎可能。

您提议的使用示例存在的问题是,在foo()before回调指定之前调用after。同时,在您的示例实现中,这些回调在foo内执行。所以 无法实现:在该方法已经运行之后,您无法追溯更改方法中发生的事情。

如果您真正想要的是通过foo提供的回调立即执行几乎 - 即,如果纯同步执行不是强制性的 - 您可以得到你的'通过简单的setTimeout电话后重新开始:

function foo() {
  var callbacks = {
    before: function() {},
    after: function() {}
  };

  setTimeout(function() {
    callbacks.before();
    setTimeout(callbacks.after, 100);
  }, 0);

  return {
    before: function(callback) {
      callbacks.before = callback;
      return this;
    },

    after: function(callback) {
      callbacks.after = callback;
    }
  };
}

此处,foo()将返回一个对象,该对象公开方法以修改callbacks方法体内关闭的foo对象。然后,这些方法将用于事件循环的下一个时钟, foo()执行后

如果您有兴趣查看此代码,我已创建an example at JSBin

答案 2 :(得分:1)

function foo(){};
foo.prototype.before = function(f){ this._before = f };
foo.prototype.after  = function(f){ this._after  = f };
foo.prototype.go = function(){
  this._before();
  setTimeout(this._after,100);
}

var f = new foo;
f.before(function(){ … });
f.after(function(){ … });
f.go();

但话又说回来,你可能会更简单:

function foo(){};
foo.prototype.go = function(){
  this.before();
  setTimeout(this.after,100);
}

var f = new foo;
f.before = function(){ … };
f.after  = function(){ … };
f.go();

答案 3 :(得分:1)

这是另一种变体:

var createFooBuilder = function () {
    var before = function() {};
    var after = function() {};

    var func = function () {
        before();
        setTimeout(function () {
            after();
        }, 100)
    };

    func.before = function(value) {
        before = value;
        return func;
    }
    func.after = function(value) {
        after = value;
        return func;
    }

    return func;
};

var foo = createFooBuilder();

foo.before(function () {
    console.log('before');
}).after(function () {
    console.log('after');
});

foo();

我当然建议您尝试让jQuery Deferred为您工作,然后您可以拥有后续功能列表。

答案 4 :(得分:1)

Phrogz的答案很好,但是你也可以在没有原型的情况下做到这一点:

function foo() {
  ret = function () { return ret.call(); };
  ret.call = function () {
    this._before();
    setTimeout(this._after,100);
  };
  ret.before = function (x) { this._before = x; return this; };
  ret.after = function (x) { this._after = x; return this; };
  return ret;
};

test = foo().before(function(){
  console.log('before');
}).after(function(){
  console.log('after');
});

通话:

test();

做你期望的事。