zoukankan      html  css  js  c++  java
  • 你所不了解的setTimeout

     

    你所不了解的setTimeout

    关于setInterval()和setTimeout()返回值

    setInterval(),setTimeout() 会返回一个值,一般认为是ID,将这个ID值传递给clearInterval(),clearTimeout() 可以取消执行,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    var intervalTimer = setInterval(function() {
        console.log(1)
    },
    3000);
    console.log(intervalTimer); //一般是一个数字,Number
    button.onclick = function() {
        clearInterval(intervalTimer);
    };

    关于setInterval()和setTimeout()中回调函数中的this

    setInterval(),setTimeout() 方法是浏览器 window 对象提供,所以第一个参数函数中的this指向window对象,这跟变量的作用域有关:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var a = 1;
    var obj = {
        a: 2,
        b: function() {
            setTimeout(function() {
                console.log(this.a); //这里返回的是:1;
            },
            2000);
        }
    };
    obj.b();

    当然你可以通过使用bind()方法来改变这个情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var a = 1;
    var obj = {
        a: 2,
        b: function() {
            setTimeout(function() {
                console.log(this.a); //这里返回的是:2;
            }.bind(this), 2000); //注意这行
        }
    };
    obj.b();

    关于bind()方法,你可以看这里:http://helloweb.wang/qianduankaifa/Js%20JQuery/2015-12-06/403.html

    关于setInterval()和setTimeout()的参数

    大家都知道setInterval()和setTimeout()可以接收两个参数,第一个参数是需要回调的函数,必须传入的参数,第二个参数是时间间隔,毫秒数,可以省略,这个可以看文章的下面,不传第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。

    但是我要说的当然不是这个,我要说的是setInterval()和setTimeout()可以接收更多的参数,那么这些参数是干什么用的呢?从第三个参数开始,依次用来表示第一个参数(回调函数)传入的参数,例如:

    1
    2
    3
    setTimeout(function(a,b){
        console.log(1+a+b);//这里打印的是:8
    },1000,3,4);

    当然一些古老的浏览器是不支持的。

    关于clearInterval()和clearTimeout()

    clearInterval()和clearTimeout()其实是通用的,就是说你可以用 clearInterval() 取消 setTimeout() 执行,clearTimeout()同样可以取消 setInterval() 执行。

    1
    2
    3
    4
    5
    6
    7
    8
    var intervalTimer = setInterval(function() {
        console.log(1)
    },
    3000);
    console.log(intervalTimer);
    button.onclick = function() {
        clearTimeout(intervalTimer); //注意这里,不是clearInterval哦
    };

    教科书里面的setTimeout

    定义很简单

    setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。

    广泛应用场景:定时器,轮播图,动画效果,自动滚动等等

    上面一些应该是setTimeout在大家心中的样子,因为我们平常使用也不是很多。

    但是setTimeout真的有那么简单吗?

    测试题

    一个题目,如果你在一段代码中发现下面内容

    1
    2
    3
    4
    var startTime = new Date();
    setTimeout(function () {    
        console.log(new Date() - startTime);
    }, 100)

    请问最后打印的是多少?

    我觉得正确答案是,取决于后面同步执行的js需要占用多少时间。

    MAX(同步执行的时间, 100)。

    再加一个题目,只有下面代码

    1
    2
    3
    4
    setTimeout(function () {
        func1();
    }, 0)
    func2();

    func1和func2谁会先执行?

    这个答案应该比较简单,func2先执行,func1后面执行。

    再来一题

    1
    2
    3
    setTimeout(function () {    
        func1()
    }, 0)

    1
    2
    3
    setTimeout(function () {    
        func1()
    })

    有什么差别?

    0秒延迟,此回调将会放到一个能立即执行的时段进行触发。javascript代码大体上是自顶向下的,但中间穿插着有关DOM渲染,事件回应等异步代码,他们将组成一个队列,零秒延迟将会实现插队操作。

    不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。

    上面答案来自《javascript框架设计》

    好了,看了上面几个题目是不是感觉setTimeout不是想象中那样了。

    setTimeout和单线程

    下面是我自己的一些理解:

    首先需要注意javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?

    简化复杂度?复杂逻辑后端处理?html5的多线程?

    上面都是ok的做法,但是setTimeout也是处理这种问题的一把好手。

    setTimeout一个很关键的用法就是分片,如果一段程序过大,我们可以拆分成若干细小的块。

    例如上面的情况,我们将那一段复杂的逻辑拆分处理,分片塞入队列。这样即使在复杂程序没有处理完时,我们操作页面,也是能得到即使响应的。其实就是将交互插入到了复杂程序中执行。

    换一种思路,上面就是利用setTimeout实现一种伪多线程的概念。

    有个函数库Concurrent.Thread.js 就是实现js的多线程的。

    一个简单使用的例子,引入Concurrent.Thread.js后

    1
    2
    3
    4
    5
    6
    7
    8
    Concurrent.Thread.create(function() {
        for (var i = 0; i < 1000000; i++) {
            console.log(i);
        };
    });
    $('#test').click(function() {
        alert(1);
    });

    虽然有个巨大的循环,但是这时不妨碍你去触发alert();

    是不是很厉害~

    还有一种场景,当我们需要渲染一个很复杂的DOM时,例如table组件,复杂的构图等等,假如整个过程需要3s,我们是等待完全处理完成在呈现,还是使用一个setTimeout分片,将内容一片一片的断续呈现。

    其实setTimeout给了我们很多优化交互的空间。

  • 相关阅读:
    2017"百度之星"程序设计大赛
    2018省赛赛第一次训练题解和ac代码
    2018天梯赛第一次训练题解和ac代码
    rsa Round #71 (Div. 2 only)
    AtCoder Grand Contest 021
    Hello 2018
    Educational Codeforces Round 36 (Rated for Div. 2)
    Codeforces Round #462 (Div. 2)
    Codeforces Round #467 (Div. 2)
    [Offer收割]编程练习赛48
  • 原文地址:https://www.cnblogs.com/wzzl/p/5026610.html
Copyright © 2011-2022 走看看