2010-09-28 2 views
7

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

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.

ответ

16

Это связано с тем, что вы используете именованные функциональные выражения, которые неправильно реализованы в IE. Удаление имен функций устранит непосредственную проблему. См. kangax's excellent article on this subject. Однако есть еще одна проблема, которая не так легко фиксируется.

В общем случае не рекомендуется пытаться переопределить свойства объектов хоста (например, 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

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

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

Хороший вопрос. Я внес изменения в свой ответ; Надеюсь, ты не против. –

+3

lol, но теперь есть ответы, говорящие то же самое:: | –

Смежные вопросы