Как вызвать исходную глобальную переопределенную функцию в JavaScript? [Дубликат]

Загрузка AJAX действительно возможна с помощью XMLHttpRequest (). Нет необходимости в iframe. Прогресс загрузки можно показать.

Подробнее см .: Ответ https://stackoverflow.com/a/4943774/873282 на вопрос jQuery Загрузка Прогресс и загрузка файла AJAX .

2
задан Lightness Races in Orbit 8 February 2012 в 15:20
поделиться

4 ответа

Существует решение, но оно не является надежным. См. Отказ от ответственности внизу.

Если вы откроете новое окно, у вас будет доступ к его немодифицированным методам. Я могу представить два способа открыть новое окно: с помощью window.open и в iframe. Iframe менее навязчив, потому что он не будет отвлекать пользователя, открывая новые окна браузера или запуская блокировки всплывающих окон.

// Runs fn with a clean window reference
function getCleanReferences(fn) {
    var iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    var newWindow = iframe.contentWindow;
    iframe.parentNode.removeChild(iframe);
    return fn(newWindow);
}

Некоторые браузеры не хотят удалять iframe. Если вы хотите, чтобы это работало в Safari или Firefox, удалите строку removeChild. Затем вы захотите получить метод getElementsByClassName из нового окна.

var nativeGetElementsByClassName = getCleanReferences(function(newWindow) {
    var getElementsByClassName = newWindow.document.getElementsByClassName;
    return function(className) {
        return getElementsByClassName.call(window.document, className);
    };
});

Это в значительной степени кросс-браузер, за исключением того, что IE не любит getElementsByClassName в режиме quirks или до версии 9 (что у вас мало контроля в букмаркете). Вот jsfiddle: http://jsfiddle.net/theazureshadow/vdqYG/

И если вам интересны мои эксперименты с импортом других методов, взгляните на этот jsfiddle : http://jsfiddle.net/theazureshadow/ccFG3/

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Использование методов из других окон в контексте текущей является опасной неопределенной территорией. Если вы решите использовать этот хрупкий подход, убедитесь, что вы проверяете совместимость с несколькими браузерами. Мои тесты показали значительные различия в том, как различные браузеры рассматривают этот подход. Вы не должны использовать это на производственной площадке, но это может быть хорошо для личного букмарклета. Вероятно, гораздо безопаснее просто включить свою версию любого метода, который вы хотите использовать.

3
ответ дан B.J. Smegma 22 August 2018 в 19:15
поделиться

Я думаю, что это невозможно. Вот почему обезболивание - это плохо. Нельзя переопределять объекты хоста.

2
ответ дан desaintmartin 22 August 2018 в 19:15
поделиться

Это зависит от того, как определяется пользовательский метод. Вы можете получить доступ к методу как Element.prototype.getElementsByClassName, но если страница перезаписывает этот метод прототипа, я не думаю, что есть способ вернуть его.

0
ответ дан J. K. 22 August 2018 в 19:15
поделиться

Я предполагаю, что некоторые сайты используют прототип. DOM document.getElementsByClassName() возвращает NodeList, тогда как document.getElementsByClassName() прототипа возвращает Array, потому что NodeList s не может быть создан JS-скриптами.

В Firefox вы можете использовать

var node = document;
Components.lookupMethod(node, 'getElementsByClassName').call(node, /* className */);

, чтобы получить исходный метод. Возможно, Google Chrome реализует нечто подобное, иначе вам не повезло. Я не мог найти ничего (2 мин. Googling).

В этом случае вы можете использовать что-то вроде этого:

function getElementsByClassName(node, className) {
    var rv = new Array();
    var nodeList = node.getElementsByTagName('*');
    className = className.replace(/([\.\\\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\-])/, '\\$1');
    var regex = new RegExp('(?:^|[\\n\\r ])' + className + '(?:[\\n\\r ]|$)');
    for(var length = nodeList.length, i = 0; i < length; ++i) {
        if(regex.test(nodeList[ i ].className)) {
            rv.push(nodeList[ i ]);
        }
    }
    return rv;
}

Если Google Chrome реализует node.classList, вы можете использовать следующая функция, которая не использует жуткое регулярное выражение:

function getElementsByClassName(node, className) {
    var rv = new Array();
    var nodeList = node.getElementsByTagName('*');
    for(var length = nodeList.length, i = 0; i < length; ++i) {
        if(nodeList[ i ].classList.contains(className)) {
            rv.push(nodeList[ i ]);
        }
    }
    return rv;
}

Эта функция выполняет итерацию по всем элементам внутри данного узла. Он возвращает Array как Prototype и имеет тот же недостаток: массивы не «живут», как NodeList s.

1
ответ дан Saxoier 22 August 2018 в 19:15
поделиться
  • 1
    Я закончил делать что-то похожее на ваше второе решение. Третье решение на самом деле не работает для меня, потому что мне нужен NodeList. В настоящее время пытается найти, есть ли эквивалентный метод webkit для метода lookupMethod Firefox. Благодаря! – asleepysamurai 8 February 2012 в 18:44
Другие вопросы по тегам:

Похожие вопросы: