今天闲来没事的时候,去逛逛segementFault,看了看别人提的问题。说到setTimeout和window.onload冲突。一开始我是挺疑惑他表他什么意思的,因为setTimeout和window.onload应该不会有明显的冲突吧。带着疑惑去追问。后来贴出代码的时候我就明白了,来看看他的代码中的疑惑吧。
window.onload=function(){setTimeout("D.style.background='#990033'",2000);}
他觉得这个代码运行的时候,setTimeout会报错,不能正确的运行指定的代码,就觉得在window.onload和setTimeout有冲突。
我对这个问题非常感兴趣。也自己试了一下,发现确实不能运行字符串里面的代码。但是还是很怀疑window.onload和setTimeout怎么可能会有冲突呢?
解决问题
为了测试方便,我就稍微改动了一下代码。将setTimeout的调用改成调用函数。
window.onload = function() { function myFun(i) { alert(1); } setTimeout('myFun(1)', 2000);}
在这里发现的确不能运行,但是这里的问题就很明显了,我将函数的调用变成了 'myFun(1)'
的字符串调用,所以会出现不能调用 myFun()
的问题。
为了深入理解我们在查询一下setTimeout的。
那么就是setTimeout只能接受函数或者是表达式的计算。那么现在答案很明显了,既是setTimeout不支持第一个参数为字符串的调用。
但是按照提问者的用法,这种 "D.style.background='#990033'"
CSS的调用也必须准守这种形式那么怎么办?
那么就服从setTimeout的规则,说干就干,将他装换成函数就好了。见以下代码。
window.onload=function(){setTimeout(function(){ D.style.background='#990033'},2000);}
这里的2秒钟之后就会执行setTimeout里面的匿名函数,即准守了setTimeout的原则,也可以利用setTimeout来调用类似字符串的形式的功能代码。
回到提问并且深入挖掘
回到提出的问题上来,深入的挖掘,其实并不是setTimeout和window.onload有冲突,在原来的问题中,其实是Javascript作用域在作怪。
在原先的问题中,如果是 setTimeout("D.style.background='#990033'",2000);
的话,由于setTimeout的第一个参数支持的是函数或者是表达式,所以字符串会被自动执行 new Function
,将这个字符串强制转换成一个函数。
我们知道在Javascript中,函数里面有自己的作用域,和外界的作用域不同,而在函数内部并没有D.style.background
这个对象,所以会有报错。在我变化的例子中,也是如此,如果使用了 setTimeout('myFun(1)', 2000)
,那么这里面的字符串就会被自动执行 new Function
,所以创建出来的函数不在这个作用域内,当然也就不能调用,会出现无法找到的问题了。