• setTimeout


     setTimeout 只能保证在指定的时间后将任务(需要执行的函数)插入任务队列中等候,但是不保证这个任务在什么时候执行。一旦执行javascript的线程空闲出来,自行从队列中取出任务然后执行它。

    1,setTimeout的好搭档“0”:

        var start = new Date();
        var end = 0;
        setTimeout(function() {  console.log(new Date() - start); }, 0);//2,或3或4

     字面意是立即执行,实际上并未立即执行;

    这是因为setTimeout有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的延迟时间设置为0,被调用的程序也没有马上启动。

    所以说,当我们写为 setTimeout(fn,0) 的时候,实际是实现插队操作,要求浏览器“尽可能快”的进行回调,但是实际能多快就完全取决于浏览器了。

    2,setTimeout(fn, 0)用处:

    其实用处就在于我们可以改变任务的执行顺序!因为浏览器会在执行完当前任务队列中的任务,再执行setTimeout队列中积累的的任务。

    3,setTimeout回调函数中的this:

    由于setTimeout() 方法是浏览器 window 对象提供的,因此第一个参数函数中的this其实是指向window对象,这跟变量的作用域有关。

    var a = 1; 
    var obj = {  
        a: 2, 
        test: function() {  setTimeout(function(){  console.log(this.a);  }, 0);  
    } 
    }; 
    obj.test(); // 1

    不过我们可以通过使用bind()方法来改变setTimeout回调函数里的this

        var a = 1;
        var obj = {
            a: 2,
            test: function() {
                setTimeout(function(){
                    console.log(this.a);
                }.bind(this), 0);
            }
        };
        obj.test(); // 2

    理解:

    再来看看浏览器下的JavaScript。

    浏览器的内核是多线程的,它们在内核控制下相互配合以保持同步,一个浏览器至少实现三个常驻线程:JavaScript引擎线程,GUI渲染线程,浏览器事件触发线程。

    • JavaScript引擎 是基于事件驱动单线程执行的,JavaScript引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JavaScript线程在运行JavaScript程序。

    • GUI渲染线程 负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(Reflow)时,该线程就会执行。但需要注意,GUI渲染线程与JavaScript引擎是互斥的,当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JavaScript引擎空闲时立即被执行。

    • 事件触发线程 ,当一个事件被触发时,该线程会把事件添加到待处理队列的队尾,等待JavaScript引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeout、也可来自浏览器内核的其他线程如鼠标点击、Ajax异步请求等,但由于JavaScript的单线程关系,所有这些事件都得排队等待JavaScript引擎处理(当线程中没有执行任何同步代码的前提下才会执行异步代码)。

    帮助理解:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="one">
        <input type="text">
        <span></span>
    </div>
    <div id="second">
        <input type="text">
        <span></span>
    </div>
    </body>
    </html>
    <script>
        document.querySelector('#one input').onkeydown = function() {
            document.querySelector('#one span').innerHTML = this.value;
        };
        document.querySelector('#second input').onkeydown = function() {
            setTimeout(function() {
                document.querySelector('#second span').innerHTML = document.querySelector('#second input').value; }, 0);
        };
        var start = new Date();
        var end = 0;
        setTimeout(function() {  console.log(new Date() - start); }, 500);//1004或1003
        while (new Date() - start <= 1000) {}
    </script>
  • 相关阅读:
    gym-102307 D. Do Not Try This Problem
    AtCoder Beginner Contest 161 E
    Codeforces 1270E 构造+数学
    2019牛客暑期多校训练营(第七场)E 线段树+离散化区间
    codeforces 1272F dp+记录路径
    Focus相关点滴
    Command模式
    接口隔离原则(ISP)
    依赖倒置原则(DIP)
    Liskov替换原则(LSP)
  • 原文地址:https://www.cnblogs.com/wang715100018066/p/6273781.html
Copyright © 2020-2023  润新知