setTimeout 和 setInterval、undefined 和 null

来源:互联网 发布:淘宝退款金额怎么修改 编辑:程序博客网 时间:2024/04/30 01:10

Javascript语言的执行环境是”单线程”(single thread)”单线程”就是一次只完成一件任务,如果有多个任务,就必须排队,等前面一个任务完成,再执行后面一个任务。这种就跟一般人的正常思维一样,也像单行道一样不堵车的时候跑起来很顺畅,但堵起来能堵死…如果其中某一个任务很耗时间的话,后面的任务就只能排队等着。很常见的像浏览器的无响应,也就是所谓的“假死”现象,我们会说先等会再操作,就是让耗时的任务执行完毕,后续任务能够依次被执行。
对这个问题,javascript也有对应的处理,即“同步模式”和“异步模式”,异步模式就显得非常重要了,在某个任务执行完后通过自身的回调函数来实现非顺序任务的执行,在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,如果所有的ajax请求我们都去设置成同步的,那本身javascript语言的“单线程”环境很明显会导致无响应现象.

可以使用 setTimeoutsetInterval 来计划执行任务:
需要注意的是这种通过上面两个函数完成定时处理并不是ECMAScript 的标准,它们在 DOM(文档对象模型) 被实现。
两者最主要区别:setTimeout只运行一次,也就是说设定的时间到后就触发运行指定代码,运行完后即结束。如果运行的代码中再次运行同样的setTimeout命令,则可循环运行。而 setinterval是循环运行的,即每到设定时间间隔就触发指定代码。我个人更习惯用setTimeout.

function testFun(){    alert("setTimeout");    }setTimeout(testFun,2000);  //如果写成testFun()就不会有定时作用,会立即被执行setTimeout("testFun();",2000);setTimeout(function(){//自己习惯的书写方式    testFun();  },2000);

上面的第一种调用方式,如果加上括号就会失去定时器作用,因为setTimeout 的第一个参数是函数对象,一个常犯的错误就是这样的 setTimeout(testFun(), 2000), 这里回调函数是testFun 的返回值,而不是testFun本身。 大部分情况下,这是一个潜在的错误,因为如果函数返回 undefinedsetTimeout 也是不会报错。
setTimeout 被调用时,它会返回一个ID标识并且计划在将来大约 2000ms后调用testFun函数。testFun函数只会被执行一次。基于 JavaScript 引擎的计时策略,以及本质上的单线程运行方式,所以其它代码的运行可能会阻塞此线程。 因此没法确保函数会在 setTimeout 指定的时刻被调用。
作为第一个参数的函数将会在全局作用域中执行,因此下面这个函数内的 this 将会指向这个全局对象。

function TestFun(){  //this是指向全局的    this.value = 20160903;    this.method = function() {        console.log(this.value);     };    setTimeout(this.method, 1000);//undefined    var self = this;    setTimeout(function(){self.method()}, 3000);//20160903}new TestFun();

setTimeout 只会执行回调函数一次,不过setInterval 会周期性执行。不太鼓励和建议使用这个函数。当回调函数的执行被阻塞时,setInterval 仍然会发布更多的回调指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。也就是所谓的setInterval 堆调用了。

function testFun(){//somecode--阻塞1000ms    }setInterval(function(){testFun();}, 100);

上面代码中,testFun会执行一次随后被阻塞了一秒钟。在 testFun被阻塞的时候,setInterval 仍然在对回调函数调用。 这种情况下当第一次testFun函数调用结束时,已经有 10 次函数调用在等待执行。处理可能的阻塞调用最简单的方法就是在回调函数内部使用 setTimeout 函数。

function testFun(){//somecode--阻塞1000ms    setTimeout(function(){testFun();},100);}setInterval(function(){testFun();}, 100);

可以通过将定时时产生的 ID 标识传递给 clearTimeout 或者 clearInterval 函数来清除定时, 至于使用哪个函数取决于调用的时候使用的是 setTimeout 还是 setInterval

var id = setTimeout(testFun, 1000);clearTimeout(id);

隐藏使用 eval的情况:setTimeoutsetInterval 也接受第一个参数为字符串的情况。 这个特性绝对不要使用,因为它在内部使用了 eval。如下:

function testFun() {//会被调用}function demo() {    function testFun() {    //不会被调用    }    setTimeout(testFun()', 1000);}demo();

由于 eval 在这种情况下不是被直接调用,因此传递到 setTimeout 的字符串会自全局作用域中执行;上面的回调函数使用的不是定义在demo作用域中的局部变量 testFun。建议不要在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。如果要传值,我们可以采用上面说的较常用的方式,通过使用匿名函数完成相同功能:

setTimeout(function(){    testFun(pra,prb,prc);},200);

对于setTimeoutsetInterval,一定不要使用字符串作为 setTimeout 或者 setInterval 的第一个参数, 这么写很明显会导致代码质量很差,工作中见到过很多这样的用法,我当时还很诧异,到底怎么用才是合适的,为什么给成字符串竟然也会被正常执行,现在知道了就要尽可能的去避免。当需要向回调函数传递参数时,可以创建一个匿名函数,如上,在函数内执行真实的回调函数。因为setInterval的定时执行不会被 JavaScript 阻塞,所以在平常的编码中还是建议尽量去避免比较好的。
下来聊一下undefinednull,两者都是javascript的基本数据类型,其余3个是BooleanNumberString,当然,复杂数据类型Object就先不提了。
这两个中感觉比较有用的应该算undefined ,很明显它是一个值为undefined 的类型;如果定义一个变量但并不给赋值,那么它的值是 undefined,这个变量也被称为 undefined。 但是这个变量不是一个常量,也不是一个关键字。这意味着它的值可以轻易被覆盖。会返回undefined的情况有以下几种:
- 访问未修改的全局变量 undefined
- 由于没有定义 return 表达式的函数隐式返回。
- return 表达式没有显式的返回任何内容。
- 访问不存在的属性。
- 函数参数没有被显式的传递值。
- 任何被设置为 undefined 值的变量。
如果一个变量没有声明就直接去访问,解释器会报错误信息,但是这样的变量如果使用typeof返回的结果也是”undefined“。Typeof很重要,因为javascript是松散类型的,在变量声明时并没有使用与之类型相对应的关键字,如果在代码中想要获知某个变量的基本数据量,就可以使用typeof。这里要注意的是typeof返回的是字符串类型。
1.”undefined”——未声明变量的值为undefined或未初始化;
2.”boolean” ——如果这变量的值是布尔类型;
3.”string” ——值是字符串类型;
4.”number” ——值是数字类型;
5.”object” ——对象或者值为null
6.”function” ——函数。
null 的用处,JavaScript 中的 undefined 的使用场景类似于其它语言中的 null,它在 JavaScript 内部有一些使用场景(比如声明原型链的终结 testFun.prototype = null),但是大多数情况下都可以使用 undefined 来代替。Null也是一个只有一个值的数据类型,任何变量只要给其赋值为null的话这个变量的数据类型就是Null类型。null值表示空对象指针,所以声明的变量要是想用来保存对象并且在声明之初还不能确定具体保存哪个对象的时候就可以将其赋值为null,在使用的时候只要检查该变量是否为null就可以知道该变量是否保存了对象。

1 0
原创粉丝点击