Изменение Javascript на странице HTML вне моего контроля [дубликат]

This question already has an answer here:

Stop execution of Javascript function (client side) or tweak it 4 answers

Я использую HTML-страницу вне моего контроля. Он определяет функцию Javascript во встроенном<script> пометить и вызывает его в<body onload="..."> :

<code><html>
...
<body onload="init()">
<script type="text/javascript" language="javascript">
    function init() {
        ...
    }
</script>
...
</code>

Как я могу изменить эту функцию до ее вызова? Я пытался использовать Greasemonkey для изменения сценария или для вставки другого сценария сразу после него, чтобы переопределить функцию, но, похоже, он не имеет никакого эффекта.

 Hawken06 мая 2012 г., 05:28
Насколько эта HTML-страница находится вне вашего контроля, если вы все еще можете изменить JavaScript на ней?
 palm3D07 мая 2012 г., 17:35
@ Hawken: Greasemonkey - это надстройка браузера для перезаписи входящего HTML непосредственно перед его рендерингом

Ответы на вопрос(2)

обычн делать такие вещи, используя thebeforescriptexecute мероприяти а также@run-at document-start. Обратите внимание, что только Firefox, кажется, поддерживает это событие, и поэтому это не будет работать в Chrome. ВидетьВо а такжеВо для более утомительных подходов.

Чтобы изменить этоinit() функция, прежде чем она вызывается, используйтеcheckForBadJavascripts() функция, которая определена ниже.

Ты бы назвал это так:

//--- New "init" function to replace the bad one.
function init () {
    //... Do what you want here...
}

checkForBadJavascripts ( [
    [false, /function\s+init(/, function () {addJS_Node (init);} ]
] );

Гдеfunction\s+init( должен быть уникальным для<script> тег, на который вы нацеливаетесь. (Обратите внимание, чтоaddJS_Node() также определяется ниже.)

Например, посетите эта страница на jsBin. Вы увидите 3 строки текста, две из которых добавлены JS.

Теперь установите следующий скрипт и вернитесь на страницу. Вы увидите, что GM-скрипт удалил один плохой<script> пометить и заменить другим нашим "хорошим" JS.

// ==UserScript==
// @name        _Replace evil Javascript
// @include     http://output.jsbin.com/tezoni*
// @run-at      document-start
// @grant       none
// ==/UserScript==

/****** New "init" function that we will use
    instead of the old, bad "init" function.
*/
function init () {
    var newParagraph            = document.createElement ('p');
    newParagraph.textContent    = "I was added by the new, good init() function!";
    document.body.appendChild (newParagraph);
}

/*--- Check for bad scripts to intercept and specify any actions to take.
*/
checkForBadJavascripts ( [
    [false, /old, evil init()/, function () {addJS_Node (init);} ],
    [true,  /evilExternalJS/i,  null ]
] );

function checkForBadJavascripts (controlArray) {
    /*--- Note that this is a self-initializing function.  The controlArray
        parameter is only active for the FIRST call.  After that, it is an
        event listener.

        The control array row is  defines like so:
        [bSearchSrcAttr, identifyingRegex, callbackFunction]
        Where:
            bSearchSrcAttr      True to search the SRC attribute of a script tag
                                false to search the TEXT content of a script tag.
            identifyingRegex    A valid regular expression that should be unique
                                to that particular script tag.
            callbackFunction    An optional function to execute when the script is
                                found.  Use null if not needed.
    */
    if ( ! controlArray.length) return null;

    checkForBadJavascripts      = function (zEvent) {

        for (var J = controlArray.length - 1;  J >= 0;  --J) {
            var bSearchSrcAttr      = controlArray[J][0];
            var identifyingRegex    = controlArray[J][1];

            if (bSearchSrcAttr) {
                if (identifyingRegex.test (zEvent.target.src) ) {
                    stopBadJavascript (J);
                    return false;
                }
            }
            else {
                if (identifyingRegex.test (zEvent.target.textContent) ) {
                    stopBadJavascript (J);
                    return false;
                }
            }
        }

        function stopBadJavascript (controlIndex) {
            zEvent.stopPropagation ();
            zEvent.preventDefault ();

            var callbackFunction    = controlArray[J][2];
            if (typeof callbackFunction == "function")
                callbackFunction ();

            //--- Remove the node just to clear clutter from Firebug inspection.
            zEvent.target.parentNode.removeChild (zEvent.target);

            //--- Script is intercepted, remove it from the list.
            controlArray.splice (J, 1);
            if ( ! controlArray.length) {
                //--- All done, remove the listener.
                window.removeEventListener (
                    'beforescriptexecute', checkForBadJavascripts, true
                );
            }
        }
    }

    /*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded.
        See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute
        Note that it does not work on acripts that are dynamically created.
    */
    window.addEventListener ('beforescriptexecute', checkForBadJavascripts, true);

    return checkForBadJavascripts;
}

function addJS_Node (text, s_URL, funcToRun) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    //--- Don't error check here. if DOM not available, should throw error.
    targ.appendChild (scriptNode);
}
 Rebs08 окт. 2015 г., 03:15
Этот код не работает для меня. Это также невероятно долго и сложно. Не говоря уже о том, что он переопределяетcheckForBadJavascripts функция внутри себя.
 Brock Adams08 окт. 2015 г., 04:35
@ Rebs, (1) Откройте вопрос с Правильный описание проблемы, если вам нужно. Код по-прежнему работает, как вы можете видеть, следуя указаниям в посте, используя Firefox + Greasemonkey. ... Я только что обновил целевую страницу, но старая была немного повреждена jsbin. Что касается ваших последних 2 баллов, вы очень не правы. Код прост для того, что он делает, и это является допустимым и полезным методом JS. Пожалуйста, удалите свое ошибочное понижение.

Следующий скрипт пользователя Greasemonkey (на основе этот источник) наконец-то сработало для меня. Он переопределяет существующую функцию, определяя другую с тем же именем в новомscript тег сразу после существующегоscript тег. Нет@run-at илиbeforescriptexecute было необходимо.

var firstScript = document.body.getElementsByTagName('script')[0];
var newScript = document.createElement('script');
var scriptArray = new Array();
scriptArray.push('function init() {');
scriptArray.push('    ...');
scriptArray.push('}');
newScript.innerHTML = scriptArray.join('\n');
scriptArray.length = 0; // free this memory
firstScript.parentNode.insertBefore(newScript, firstScript.nextSibling);

У меня не было большого опыта работы с Greasemonkey или даже с Javascript, поэтому я нашел инструменты Firefox Web Developer незаменимыми, в частности:

Консоль ошибок, чтобы поймать множество мелких ошибок, которые вы обязательно сделаете. а такж Инструмент проверки, чтобы увидеть полученный HTML-код (потому что обычный источник просмотра не показывает этого!).
 Brock Adams08 мая 2012 г., 00:51
Если это работает, я считаю, что это просто удача. Он устанавливает «условие гонки», что означает, что, хотя он может работать на некоторых страницах, иногда он не должен работать на других страницах, в зависимости от их состава.

Ваш ответ на вопрос