【问题标题】:Monkey-patching a named function that's called immediately猴子修补一个立即调用的命名函数
【发布时间】:2015-01-06 11:36:42
【问题描述】:

我正在加载的脚本行为不端。它的结构是这样的:

function bad_function() {
    ...
}

/* randomly generated stuff */

bad_function();

如果在脚本末尾立即调用bad_function,我该如何修改它的行为?我想在加载脚本之前在window 上创建一个静默只读属性,但是在执行上述脚本时会引发TypeError: Identifier 'bad_function' has already been declared 异常:

Object.defineProperty(window, 'bad_function', {
    value: function() {
        /* my monkey-patched code */
    }
});

如何对这个函数进行猴子补丁?

【问题讨论】:

  • 您在使用 Chrome 吗?这是您面临的特定于浏览器的问题吗?
  • @jjk_charles:不,它与浏览器无关,是脚本的问题。
  • 您是在与原始 bad_function() 相同的 JS 文件中使用“defineProperty”,还是在不同的文件中?如果不同的文件,
  • @jjk_charles:我不能修改包含bad_function的脚本,但是我可以修改加载它的页面。

标签: javascript monkeypatching


【解决方案1】:

虽然这不是一般问题的答案,但我可以通过修补像 encodeURIComponent 这样在我的函数内部调用的全局函数、执行必要的更改并抛出一个异常以防止原始函数的其余部分运行。

var old_encodeURIComponent = window.encodeURIComponent;

window.encodeURIComponent = function() {
    // If this function is used in multiple places, look for variables in
    // the current scope to determine if this is the right spot to start 
    // monkey patching.
    if (typeof a === 'undefined' || typeof b === 'undefined') {
        return old_encodeURIComponent.apply(this, arguments);
    }

    // You now have access to the variables in the scope of your target 
    // function. If your monkey patching is just a simple tweak, you're all set

    // Otherwise, do what you need to do and throw an exception to stop the
    // rest of the code from running

    throw 'goodbye';
};

【讨论】:

    【解决方案2】:

    这不是很好,但我能想到的就是通过 ajax 加载脚本,而不是将其放在 <script> 标记中,操纵结果字符串以调用您自己的函数版本(或“重命名”@ 987654323@ 所以它不会覆盖您的版本),然后将 that 放在 <script> 标记中并将其附加到您的页面:

    为简单起见使用 jQuery 的示例:

    function good_function() {
        alert("I am good");
    }
    
    $.ajax({
        url: '/echo/html/',
        type: 'POST',
        data: {
            html: "function bad_function() { alert('hahaha'); } bad_function();",
            delay: 0
        },
        success: function(data) {
            console.log(data);
    
            // comment this line to see the original
            data = data.replace('bad_function();', 'good_function();')
    
            var newScript = $('<script type="text/javascript" />').text(data);
            $('body').append(newScript);
        }
    });
    

    Working JSFiddle

    【讨论】:

    • 重命名 bad_function 会破坏猴子修补的全部意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多