zoukankan      html  css  js  c++  java
  • JavaScript setTimeOut()方法的一些疑点自己记录

    原由:

      自己刚在研究js的防抖引发的一个问题(因为不在本篇范围不说了奥),代码:  

       var count = 1;
        var container = document.getElementById('container');
    
        function getUserAction() {
            container.innerHTML = count++;
        };
    
        function debounce(f, t) {
            let tid;
            return function() {
           if(tid) {
             clearTimeout(tid);
           }
                tid = setTimeout(f, t);
            }
        }
        container.onmousemove = debounce(getUserAction, 3000);

    如上所示,基本防抖都有了,但是我想指定getUserAction中的this给debounce,我这个时候就脑缺了...

       var count = 1;
        var container = document.getElementById('container');
    
        function getUserAction() {   // this 指向 window
    container.innerHTML
    = count++; }; function debounce(f, t) { let tid; return () => { // this肯定指向 document.getElementById('container')的html元素
          if(tid) {
             clearTimeout(tid);
          }
             tid = setTimeout(f.call(this), t); 
      }
       }
    container.onmousemove
    = debounce(getUserAction, 3000);

    自己去运行下啊,这时候发现当鼠标移动在container范围中,会失去防抖的功能,也就是说,setTimeOut根本没有执行!!!!(自认为)

    其实眼见的同学已经发现了,f.call(this)其实已经执行了该函数,而不是函数声明或者code

    根据MDN的解释:

    var timerId = setTimeout(func|code, delay)
    functionfunction 是你想要在到期时间(delay毫秒)之后执行的函数
    code这是一个可选语法,你可以使用字符串而不是function ,在delay毫秒之后编译和执行字符串 (使用该语法是不推荐的, 原因和使用 eval()一样,有安全风险)。
    delay 可选延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟之后发生。如果省略该参数,delay取默认值0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的(delay毫秒数) 值长,原因请查看Reasons for delays longer than specified

    所以,答案很明显了!!!代码改下啊:

       var count = 1;
        var container = document.getElementById('container');
    
        function getUserAction() {   // this 指向 window
    
            container.innerHTML = count++;
        };
    
        function debounce(f, t) {
            let tid;
            return () => {   // this肯定指向 document.getElementById('container')的html元素
          if(tid) {
            clearTimeout(tid);
          }
              tid = setTimeout(() => {   // 更改为function就行了
            f.call(this)
          }, t); 
          } 
       } 
        container.onmousemove = debounce(getUserAction, 3000);

    那么这个问题解决了啊.好了本文到此结束!!!!

    开....开玩笑的奥,是这样的,这时候的确是解决问题了,但我自己想了下,那 tid = setTimeout(f.call(this), t); 到底有没有执行!!!!!

    经过,我多方的考证以及最近看了<<你不知道的js>>中了解到,其实在js中存在一个内部的任务队列,用于存储异步任务(setTimeOut,点击事件的回调函数等)

    举个栗子:

    setTimeout(() => {
        console.log(1);
    },0)
    
    console.log(2); 
    // result : 2 1

    其实,通俗来说同步的任务会按照代码顺序来执行函数,而异步的(当前就是setTimeOut会加入任务队列,即使它的delay为0)

    那我们再来个demo,体现有序的队列:

    setTimeout(() => {
            console.log(1);
        }, 200)
        setTimeout(() => {
            console.log(2);
        }, 100)
        console.log(3);
    
        setTimeout(() => {
            console.log(4);
        }, 0)   // 根据delay的长短来顺序加入任务队列
        console.log(5);
    // 3 5 4 2 1

    说这么多,我就想说明.既然你声明了定时器,那肯定会加入任务队列去执行的.那问题来了,那我的f.call(this)去哪了?众所周知,js中若function没有指定return,默认是返回undefined的,那是不是代表.我的setTimeout(undefined,1000)这样执行了!!!

    为了,验证想法,我们可以改下函数的内容    var count = 1;

    var container = document.getElementById('container');
    
        function getUserAction() {
    
            container.innerHTML = count++;
            return `alert('done')`;
        };
    
        function debounce(f, t) {
            let tid;
            return () => {
          if(tid) {
            clearTimeout(tid);
          } 
              tid = setTimeout(f.call(this), t);
         }   
      }
      container.onmousemove
    = debounce(getUserAction, 3000);

    果然,出来一个alert!!!!!!!那么,到此也就证明了,我们的定时函数还是执行了的~~~~

    总结下,setTimeout()第一个参数还是一个function声明,不要直接执行function.或者,在一定需要的时候,去让函数返回这个需要执行的code或function(就和闭包这样的直接return function).

    不说了,还是自己太大意了,哈哈哈哈哈~~~~

  • 相关阅读:
    大学毕业4年-回顾和总结(10)-资金账务系统的架构设计(产品视角+技术视角)(图文并茂)
    大学毕业4年-回顾和总结(10)-资金账务系统的架构设计(产品视角+技术视角)(图文并茂)
    Spring核心技术(六)——Spring中Bean的生命周期
    商业研究(20):滴滴出行,进军海外包车?与OTA携程和包车创业公司,共演“三国杀”?看看分析师、投资人和权威人士等10个人的观点碰撞
    商业研究(20):滴滴出行,进军海外包车?与OTA携程和包车创业公司,共演“三国杀”?看看分析师、投资人和权威人士等10个人的观点碰撞
    玩转Android之二维码生成与识别
    大学毕业4年-回顾和总结(9)-股权投资1年,给自己一个答卷(好狗狗、皇包车、职业梦、比呀比、易途8)(创业有风险,投资需谨慎)
    大学毕业4年-回顾和总结(9)-股权投资1年,给自己一个答卷(好狗狗、皇包车、职业梦、比呀比、易途8)(创业有风险,投资需谨慎)
    【Raspberry pi】系统安装及基础配置
    【python】字符串编码问题
  • 原文地址:https://www.cnblogs.com/mikusnail/p/11401642.html
Copyright © 2011-2022 走看看