在 javascript 中向第 3 方闭包添加函数

add a function to a 3rd-party closure in javascript

好的,我不认为在 C# 中执行此操作,但 javascript 的设计具有更大的访问灵活性。

有这样的插件

(function($)
{
    ...more stuff
    var results={a:1,b:2}  //this I need to modify
    var someData={x:1}
    send = function(){
        //send results ajax
    };

    if(typeof beforeSend=='function')
        beforeSend(someData) //hook to use results
})(jQuery)

所以,在我自己的代码中,我有函数 window.beforeSend = function(d){}

它确实有一些数据在我需要修改的范围内。但问题是: 我如何在发送之前 修改 闭包中的 results var。 我需要添加

window.beforeSend = function(d){
    window.quantumTunnelThroughScope.results['c']=1
}

我需要这样做的原因是因为我无法修改插件的代码。当然,如果我在闭包中添加 beforeSend,它会起作用,但是我正在修改库,在这种情况下我不允许这样做。

我见过一些很棒的 eval('this.xx' =function ) 等等,但我无法让它工作。

编辑: 我澄清说实际上它是需要编辑的相同范围内的不同变量

不,beforeSend 没有合理的 方式进入闭包并修改 resultsresults 在所提供的代码中,该闭包中的代码完全私有。

不合理尝试的方法是通过eval反编译和重新编译插件函数,并且在 beforeSend 之前插入一个函数调用,让我们修改 results:

(function($) {
  $.run = function() {
    // You mentioned "ajax," so let's make this
    // asynchronous
    setTimeout(function() {
      var results = {
        a: 1,
        b: 2
      };
      var someData = { // Need to modify this
        x: 1
      };
      send = function() {
        //send results ajax
      };

      if (typeof beforeSend == 'function') {
        beforeSend(someData); //hook to use results
      }

      console.log("in plugin, results = ", results);
    }, 10);
  };
})(jQuery)

window.modifyResults = function(d) {
  return ["new", "results"];
};
window.beforeSend = function(r) {
  r.c = 1;
};

jQuery.run = (function() {
  // Function#toString, on nearly all browsers, returns the source
  // code of he function (or something near to it) except on functions
  // implemented in native code. We take that string and replace
  // the "beforeSend(someData);" call with two calls, the first of
  // which lets us modify the `results` variable. Then we use eval
  // to turn that back into a function, and assign the result to
  // where the plugin put its function originally.
  return eval("(" + jQuery.run.toString().replace(
    "beforeSend(someData);",
    "results = modifyResults(results); beforeSend(someData);"
  ) + ")");
})();

jQuery.run();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

但可能会或可能不会工作,这取决于插件的编写方式,因为它将它从其原始范围中移除并在我们的函数更新范围内重新编译它 jQuery.run

我想我更愿意冒险修改插件。 :-)


注意:在上面,我使用了 "static" jQuery 函数。如果您要替换的插件提供了一个 instance 函数,您可以在 jQuery 个实例上调用这种函数,例如$(".foo").bar() 中的 bar,您会在 jQuery.fn 而不是 jQuery:

上找到它
jQuery.fn.pluginFunction = eval(...);