переопределение глобальной функции в JavaScript - PullRequest
9 голосов
/ 28 сентября 2010

Я пытаюсь добавить свою собственную обработку ошибок в функцию JavaScript setTimeout.Следующий код прекрасно работает в chrome:

var oldSetTimeout = window.setTimeout;
window.setTimeout = function setTimeout(func, delay) {
    var args = Array.prototype.slice.call(arguments, 0);
    args[0] = function timeoutFunction() {
        var timeoutArgs = Array.prototype.slice.call(arguments, 0);
        try {
            func.apply(this,timeoutArgs);
        }
        catch (exception) {
            //Do Error Handling
        }
    }
    return oldSetTimeout.apply(this, args);
}

Но в IE7 он превращается в рекурсивную функцию.По какой-то причине oldSetTimeout получает новую функцию.

Есть предложения?



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

Ответы [ 2 ]

18 голосов
/ 28 сентября 2010

Это потому, что вы используете выражений именованных функций , которые неправильно реализованы в IE.Удаление имен функций решит непосредственную проблему.См. kangax отличную статью на эту тему .Однако есть еще одна проблема, которую не так легко решить.

В общем случае не стоит пытаться переопределять свойства хост-объектов (таких как window, document или любой элемент DOM)потому что нет никакой гарантии, что окружающая среда позволит это.Хост-объекты не связаны теми же правилами, что и нативные объекты, и по сути могут делать то, что им нравится.Также нет гарантии, что метод хоста будет объектом Function, и, следовательно, oldSetTimeout не всегда может иметь метод apply().В IE это так, поэтому вызов oldSetTimeout.apply(this, args); не будет работать.

Вместо этого я бы предложил следующее:

window.oldSetTimeout = window.setTimeout;

window.setTimeout = function(func, delay) {
    return window.oldSetTimeout(function() {
        try {
            func();
        }
        catch (exception) {
            //Do Error Handling
        }
    }, delay);
};
3 голосов
/ 16 июля 2013

Незначительное улучшение Ответа Тима Дауна, чтобы подражать оригиналу еще больше:

window.oldSetTimeout = window.setTimeout;
window.setTimeout = function(func, delay) {
    return window.oldSetTimeout(function() {
        try {
            func();
        }
        catch (exception) {
            //Do Error Handling
        }
    }, delay);
};
...