【问题标题】:overriding a javascript function's return statement覆盖 javascript 函数的 return 语句
【发布时间】:2012-01-11 19:33:09
【问题描述】:

假设我有一个 js 函数。从程序的其他点开始,我想运行它的代码,而不是它的 return 语句。取而代之的是,我想运行其他一些引用原始函数范围内变量的返回语句。

除了加载函数源、替换 return 并在结果上使用 eval 之外,还有其他方法吗?原件的最小修改是可能的,尽管它不应该通过添加例如影响原件的性能。一个额外的函数调用。

【问题讨论】:

  • 对不起,在手机上,虽然我可以在一个小时左右发布一些。
  • #1 - 您可以使用 AOP 更改返回,但您将无法访问内部变量。 #2 - 您可以在原始函数的 .toString() 上使用新函数,插入新代码。您将拥有完全访问权限,但这被视为垃圾代码。

标签: javascript metaprogramming


【解决方案1】:

你可以试试这样,但我不确定它是否符合你的条件。

编辑:固定在 jsfiddle 中工作

// Modified to set all "shared" variables as "members" of the function.
var test = function() {
    test.val = "one";
    test.val2 = "two";
    return 1;   
}

// Using different result
function test2() {
    test();
    return test.val2;
}

【讨论】:

  • 你不需要调用 test 作为构造函数吗?
  • @AdamRackis 如果您不调用 test 作为构造函数,则调用 this === window
  • 我很惊讶这个答案得到了两个赞成票,因为它既不正确,也不是操作员要求的......
  • @dzejkej - 答案中发布的代码不起作用..请参阅jsfiddle.net/hUaJD
  • @dzejkej - 是的,完全正确。所以该函数会将 val 和 val2 添加到 window 对象,并返回 1。然后你怎么能说 test.val2;
【解决方案2】:

您可以引入一个回调函数,如果可用,它将被调用,否则将返回“标准”值。

function test(callback) {
  // ...
  return callback ? callback.call(this) : /* original value returned */ "xyz";
}

test(function() { /* "this" is same as in test() */ });

编辑:

如果您想在回调中传递变量,那么您只需在 .call() 函数中列出它们。

示例:

function test(callback) {
  var a = 4;
  var b = 2;
  // ...
  return callback ? callback.call(this, a, b) : a * b;
}

test(); // 8
test(function(a, b) { return a + b; }); // 6

this fiddle

【讨论】:

    【解决方案3】:

    除非您能够重组您的方法以适应 callback 或引入其他一些基于参数的逻辑流程(不是第 3 方代码的选项),否则您将不走运。

    这是一个回调示例(fiddle,感谢 dzejkej's answer

    function foo(callback) {
        var x = 2;   
        // pass your values into the callback
        return callback ? callback.call(this, x) : x * 2;
    }
    document.write(foo());
    document.write("<hr/>");
    // specify the parameters for your callback
    document.write(foo(function(x){ return x * 4;}) );
    

    【讨论】:

    • 你读过这个问题吗? “有没有办法做到这一点,除了 (...) 源,替换返回,并在结果上使用 eval?可以对原始文件进行最小的修改”
    • 我可以修改原来的,只要我保持它的性能稳定。
    • 我在我的答案中放了一个例子,然后意识到你之前也做过同样的事情:)。我会把它留在那里以获得更完整的答案。但是 +1 给你。
    【解决方案4】:

    我觉得你真的误解了return statement的概念。如果没有指定 return parameter,函数的 return 语句将简单地返回一个值、一个对象或 undefined。

    如果您只想执行一个函数而不是“不是它的返回语句”,那么您将只调用该函数而不对返回的值/对象做任何事情:

    但是,如果您的意思是您想要执行一个函数但不执行其返回语句的“参数”,那么这实际上意味着有选择地执行函数体的任意部分。据我所知,这是不可能的(不使用反射来获取函数定义,修改定义,然后动态调用修改后的版本 - 你说你不想这样做)。

    【讨论】:

    • 取决于您是否将参数计为语句的一部分,但您的第二个选项是正确的。将尝试适当地编辑问题
    • @AlexandrosMarinos - 您是否可以控制原始功能(即您是否可以选择重写该功能)?显然,如果你这样做 - 这会改变你可以做的事情来模拟你正在寻找的行为。
    • 是的,我确实有这个选项,但受限于保持其性能不变的需要。你在想什么?
    • @AlexandrosMarinos 向函数添加一个参数,以启用/禁用执行您不想执行的代码部分。添加类似的东西肯定不会对函数的性能产生太大影响(它本质上只是另一个分支条件)
    【解决方案5】:

    如果您将外部作用域函数的变量保留在单个对象中,您可以尝试以下操作:

    function original(a, b, c, rep) {
        var data = {};
    
        // Do some fancy stuff but make sure to keep everything under data
        data.a = a.replace(/foo/, 'bar');
        ...
    
        if ( Object.prototype.toString.call(rep) === '[object Function]' )
            return rep.call(data);
    
        return data;
    }
    
    function replacement() {
        return 'foo' + this.a;
    }
    
    // Now let's make use of both the original and the replacement ...
    console.log(original('foo', x, y)); // => {a: "bar", b: ...}
    
    console.log(original('foo', x, y, replacement)); // => {a: "foobar", b: ...}
    

    希望,这就是您所要求的。
    干杯

    【讨论】:

      猜你喜欢
      • 2017-12-24
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 2013-12-13
      • 2015-12-04
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      相关资源
      最近更新 更多