setTimeout 第一个参数

今天有人在群里问setTimeout第一次参数为字符串的时候为什么会报错,代码如下:

 function display(obj)
{
    obj.style.display='none';
    window.setTimeout("obj.style.display='inline'", 500);
}

报obj is not defined。

经过我自己测试了列子,自己总结出了几个结论,真实性有待考证。下面讲讲我的例子与结论。

首先,setTimeout的第一个参数分为3类,1.字符串代码 2.method 3.function 。

1.字符串代码:

function display(obj)
{
    obj.style.display='none';
    window.setTimeout("obj.style.display='inline'", 5000);
}

当setTimeout第一个参数为字符串代码时,执行这段代码会报obj未定义,原因是因为setTimeout方法是window的方法,是个全局方法。执行这个方法的代码的作用域环境是window。

obj是当初display方法的参数传进来的,是个局部变量。在window下找不到obj这个变量所以报未定义。

2.method:

在这儿我把method和function区分开了,区别在哪儿呢?代码如下:

function display(obj)
{
    obj.style.display='none';
    window.setTimeout("fn(obj)", 5000);
}

function fn(o){
    o.style.display='inline'
}


像上面代码一样执行,还是会报obj未定义,原因和上面一样的,这儿调用的fn()是全局方法,它的参数obj在全局变量中找不到。

这个和参数为function的区别在于,method是定义好了方法,当成第一个参数传过setTimeout(),而function是在第一个参数的位置定义function,两者有很大的区别,下面会讲解。

注意,这儿提醒下,我在写代码的时候犯了个错误,代码如下:

function display(obj)
{
   obj.style.diaplay='none';
  window.setTimeout(fn(obj),500);    
}
function fn(0){
   o.style.display='inline';
}

我把fn(obj)的引号去掉了,这样的写法是错误的,这样写,fn会被立即调用,而不是500毫秒之后。

3.function:

function display(obj)
{
   obj.style.diaplay='none';
  window.setTimeout(function(){ obj.style.display='inline';},500);    
}

这种写法是把function直接写在了setTimeout的第一个参数位置,这样写就和display()形成了一个闭包。所以setTimeout执行function的时候display的作用域是存在的。

这样就会先去display()的作用域找obj这个变量,obj是当方法的参数传进来的,所以是能找到的。这样就能正确的执行这段代码。

总结:

 要解决这种问题又两个方法,第一:把obj声明成全局变量,setTimeout是可以调用的。全局变量会一直存在,直到页面关闭。

 第二种:把setTimeout方法的第一个参数写成function,这样形成一个闭包来访问局部变量。但是闭包会使得它的父函数的变量和方法一直处于内存,直到闭包函数调用结束。

此两种方法各有优缺点,根据自己的需求来取舍。

原文地址:https://www.cnblogs.com/webhelper/p/3711888.html