La explicación y la solución son in the MDN:
Si tiene que pasar un argumento a la función de devolución de llamada, pero necesita para trabajar en Internet Explorer, que no soporta el envío parámetros adicionales (ni con setTimeout() ni setInterval()) puede incluir este código de compatibilidad específica de IE que habilitará la funcionalidad de paso de parámetros estándar HTML5 de en ese navegador para ambos temporizadores simplemente insertándolo al principio de sus scripts.
if (document.all && !window.setTimeout.isPolyfill) {
var __nativeST__ = window.setTimeout;
window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
var aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeST__(vCallback instanceof Function ? function() {
vCallback.apply(null, aArgs);
} : vCallback, nDelay);
};
window.setTimeout.isPolyfill = true;
}
if (document.all && !window.setInterval.isPolyfill) {
var __nativeSI__ = window.setInterval;
window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
var aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeSI__(vCallback instanceof Function ? function() {
vCallback.apply(null, aArgs);
} : vCallback, nDelay);
};
window.setInterval.isPolyfill = true;
}
Esto me tomó una hora o dos para averiguar por qué mi variable ámbito externo w como 'indefinido'. ¡Internet Explorer es el peor! –