猴子修补一个立即调用的命名函数

Monkey-patching a named function that's called immediately

我正在加载的脚本出现问题。它的结构如下:

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 */
    }
});

如何猴子修补这个函数?

不太好,但我能想到的就是通过 ajax 加载脚本而不是将其放在 <script> 标记中,操作结果字符串以调用您自己的版本函数(或 "rename" bad_function 所以它不会覆盖你的版本),然后将 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

虽然这不是我一般问题的答案,但我能够通过修补在我的函数内部调用的 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';
};