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

时间:2015-01-06 11:36:42

标签: javascript monkeypatching

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

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

如何对此功能进行猴子修补?

2 个答案:

答案 0 :(得分:0)

它并不好,但我能想到的只是通过ajax加载脚本而不是将它放在<script>标签中,操纵结果字符串来调用你自己的函数版本(或&#34;重命名&#34; bad_function因此它不会覆盖您的版本),然后将 放在<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

答案 1 :(得分:0)

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