【问题标题】:Insert code into body of function at runtime在运行时将代码插入函数体
【发布时间】:2015-03-11 10:25:34
【问题描述】:

来自 Java 并具有字节码编辑经验,我想知道是否可以在运行时使用 Javascript 更改函数体。

对于这个问题,我们以下面的代码为例:

function myFunction(paramA, paramB) {
    console.log('a', paramA);

    console.log('b', paramB);
}

在运行时,我希望能够将 body 更改为:

function myFunction(paramA, paramB) {
    console.log('a', paramA);
    console.log('hello inserted world');
    console.log('b', paramB);
}

如果可能的话,我知道它将增加代码库的复杂性。因此,如果可能的话,应该避免在小组项目中(或者当有人最终必须接管时),但这不是现在的问题。

真正的问题是,这是否可能(或者可以近似)以及如何去做?我不是在寻找代码示例,伪就足够了!

一些要求/规则/注意事项:

  • 该示例包含函数声明,但也可以使用函数表达式。
  • 该函数可能被完全覆盖;现有的参考资料可能会丢失。
  • 整个应用程序将被缩小,答案应该考虑到这一点。
  • 插入的代码必须紧跟在第一个 console.log 之后,不管正文中可能有也可能没有其他代码。
  • 该函数必须可以通过myFunction(a, b) 执行。

【问题讨论】:

  • 如果注入仅针对 console.log 调用,您可以按照以下方式工作:1. console.log = function () { /* whatever */ };。将检测调用站点+要注入的代码所需的所有逻辑添加到函数体中。 2.delete console.log;。恢复原来的console.log,
  • 哈哈很有创意,但是因为console.log只是一个例子,在现实世界中是没有用的。除此之外,这涉及到准备原始函数,如果这样做,为什么不自己添加代码呢? ;-)
  • 当您的代码不会被缩小或您知道缩小器的名称修饰方案时,该方法推广到 myFunction 调用。否则它需要一个定义的钩子,例如。未缩小的 js 运行时调用。在任何情况下,它涉及准备原始函数:您将要插入的代码移动到新的“console.log”中并添加一些检查以确定何时执行它...
  • ... 是否可行取决于您需要的灵活性。

标签: javascript code-injection


【解决方案1】:

我想这取决于代码的来源。 JavaScript 的eval() 语句总是存在,但由于可能存在安全漏洞,通常(强烈)不鼓励使用它。见this article

【讨论】:

    【解决方案2】:

    更改函数以便您可以使用原型

    http://www.w3schools.com/js/js_object_prototypes.asp

    【讨论】:

      【解决方案3】:

      您可以使用 eval 实现此目的,但它通常被认为是“邪恶”,所以请小心。

      eval 可以评估以字符串形式传递给它的代码 - 非常危险。

      您可以将myFunction 更改为简单地执行eval 并传递您想要的任何内容。

      function myFunction(a,b,evil) {
        eval(evil); //do whatever you want with a, b and evil.
      }
      

      您必须用上述声明覆盖myFunction(a,b)

      【讨论】:

      • 将函数更改为字符串,插入字符串,然后编译/评估回函数。但是使用字符串,我必须自己识别行尾等,如果源被缩小,这可能会很困难(我现在将其添加到 OP 中)
      • @SD 这是允许重写函数的js。它还允许将函数检索为字符串。 eval 只是将字符串评估为 js。
      • 那个 object.prop 和 object['prop'] 是一回事(所以请不要再使用 eval,谢谢);该对象属性始终是字符串(即使对于数组);什么 for...in 是为了(以及它不是什么)。 stackoverflow.com/questions/2628672/…
      • @StephanBijzitter 行尾如果缩小,则不应作为目标,指令终止符将是有效目标 (;)
      【解决方案4】:

      这可能不符合你想要的方式,但这是“真正的”JS 方式。你真的不应该使用 eval 什么的。这是面向对象的js。

      var ov = {};
      
      //the function
      var myFunction = function(paramA, paramB) {
          console.log('a', paramA);
          console.log('b', paramB);
      };
      
      //Add something to the function
      var dispatch = function(object, method, args){
       method.apply(object, args);
       //do whatever you want beneath this line
       console.log('hello inserted world'); 
      };
      
      dispatch(ov, myFunction, ["pa", "pb"]);
      

      我们在这里所做的是创建一个空对象。将这两个参数实际实现到对象中可能是有意义的,但这是另一回事。 我们正在创建一个函数“myFunction”和一个调度程序,并在调度程序函数中调用该函数(通过“应用”)。 之后,我们可以根据需要添加代码。我们现在能够在 ov 的范围内执行调度函数。我们通过数组传递参数。

      【讨论】:

      • 您的解决方案会以错误的顺序产生输出,不是吗? ('a','pa','b','pb','hello...' 而不是 'a','pa','hello...','b','pb')跨度>
      • 这是缺点=)
      猜你喜欢
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      相关资源
      最近更新 更多