避免重新绑定函数引用中的递归

时间:2013-03-26 11:44:38

标签: javascript function recursion reference

X反复尝试调用其方法foo,严重损害了我的插件Y的用户体验。我的插件Y引入了在shouldFooExecute最终结果发生之前必须考虑的任意逻辑X.foo。但是,当用户在Y(在模态窗口中)的旅程完成后,X应该可以继续进行,就像没有发生任何事情一样。

// This is an external library. I can't modify and shouldn't overwrite it.
x = {
  // A method that completely screws my plugin
  foo: function(){
    /* nasty stuff */
  }
}

// This is my widget!
y = {
  // Init function, called when my plugin boots
  init: function(){
    // This scope handles the x.foo problem
    void function rebindFoo(){
      // Internal state
      var shouldFooExecute = false;
      // I need to be able to refer back to the original foo after I've temporarily rebound it
      var x_foo = x.foo;

      // Re-attach foo to its original definition & context
      function rebindFooToX(){
        // ECMAScript 5 browsers are fine!
        if(Function.prototype.bind){
          // x.foo is literally rebound to pretty much exactly what it was
          x.foo = x_foo.bind(x);
        }
        // Others not so good when this function executes a second time
        else {
          x.foo = function rebound_foo(){
            // An extra scope! Horrible. And it's recursive!
            return x_foo.apply(x, arguments);
          }
        }
      }

      x.foo = function y_foo(){
        // Stop and consider y's esoteric logic
        if(shouldFooExecute){
          // If it's fine, we rebind everything
          rebindFooToX();
          // This will have the intended effect
          x.foo();
        }
      }
    }
  }
}

当我的插件在不支持bind的浏览器上重新初始化时出现问题。 x.foo最终引用rebound_foo,这是循环的。我是否可以编写任何逻辑来避免递归并在存在的情况下使用现有的rebound_foo

2 个答案:

答案 0 :(得分:0)

您可以使用https://github.com/kriskowal/es5-shim向本机不支持的浏览器添加Function.prototype.bind方法。

答案 1 :(得分:0)

事实发生后7个月,所以这个问题可能是OBE,但是我想要注意,根据X的定义方式,你可以尝试继承:

var x = function() {
    this.foo = function() {
        console.log("from x");
    };

    this.bar = function() {
        console.log("from x");
    };
}

var y = function() {
    this.foo = function() {
        console.log("from y");
    }
}

y.prototype = new x();

var test = new y();
test.foo(); // will output: from y
test.bar(); // will output: from x