今天闲来没事的时候,去逛逛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() 的问题。

为了深入理解我们在W3school查询一下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 ,所以创建出来的函数不在这个作用域内,当然也就不能调用,会出现无法找到的问题了。


猫仔面
328 声望2 粉丝

chanchun.net