覆盖函数中的函数

时间:2016-05-17 20:24:13

标签: javascript extend

我想弄清楚如何扩展:

var outdatedBrowser = function(options) {
  function startStylesAndEvents() {
   console.log("bleh");
  }
}

我试图覆盖函数startStylesAndEvents而不触及库的源代码:https://github.com/burocratik/outdated-browser/blob/develop/outdatedbrowser/outdatedbrowser.js

所以当我打电话时:

outdatedBrowser({
    bgColor: '#f25648',
    color: '#ffffff',
    lowerThan: 'transform',
    languagePath: 'your_path/outdatedbrowser/lang/en.html'
})

它使用startStylesAndEvents函数,它使用我的而不是他们的......

谢谢!

4 个答案:

答案 0 :(得分:2)

不修改原始来源?你不能。

所有JavaScript范围都基于函数(暂时忽略letconstclass。如果在函数内部声明了一个值,则除非从函数返回或修改某个外部值,否则不能在该函数外部访问它。

例如,想象一下这样的函数:

function doStuff() {
  var times = 10;
  for (var i = 0; i < times; i++) {
    doThing(i);
  }
}

您的问题在语义上与询问如何更改times相同。它无法完成。

答案 1 :(得分:2)

内部函数包含在一个您无权访问的闭包中。不幸的是(与“没有不可能的”意识形态相反),这不能在运行时完成。

答案 2 :(得分:0)

这就是你所谓的'私人'功能。该函数与任何其他变量一样存储。在JavaScript中,通常意味着它必须是“本地范围”(而不是成员变量),因此无法覆盖它。 (如果他们只使用过this.functionName ...那么你可以更轻松地覆盖)

好消息是,有一个似乎是跨浏览器兼容的黑客。 (在IE 11中测试,仿真选项返回到IE 5!)在JavaScript中,您可以替换函数本身的实际“源代码”。 (与正确的覆盖略有不同)

var newInnerFunction = function () { // intentionally anonymous for use in eval
}
var overriddenFunction = eval(
    outdatedBrowser.toString() // expecting outdatedBrowser to be anonymous for use in eval
    .replace('{', '{var startStylesAndEvents=' + newInnerFunction.toString() + ';')
)

请注意,outdatedBrowser是一个匿名函数(只是function())。如果它被命名,则使用eval会产生将新函数添加到其原始名称下的命名空间的副作用。如果这是一个问题,额外的replace可以解决这个问题。

答案 3 :(得分:0)

最有可能的是,你不能。但这并非完全不可能。

例如,如果在范围对象泄露到外部的startStylesAndEvents语句中调用with

var scope = Object.create(null);
var outdatedBrowser = function(options) {
  function startStylesAndEvents() {
     console.log("bleh");
  }
  with(scope) {
    startStylesAndEvents(); // You expect this to be the private function above
  }
}
outdatedBrowser(); // "bleh"

然后,您可以劫持对startStylesAndEvents的呼叫:

scope.startStylesAndEvents = function() {
  console.log("blah");
};
outdatedBrowser(); // "blah"

当然不要这样做。它是邪恶的,缓慢的,不允许在严格的模式下。