美文网首页
Javascript定时器

Javascript定时器

作者: aabbcczero | 来源:发表于2020-04-10 18:55 被阅读0次

什么是定时器?

javascript延时执行的代码即为定时器。定时器通常有两个函数组成:

setTimeout

setInterval

定时器的作用场景?

轮播图,广告弹窗,动画, 异步等

定时器的用法和区别?

setTimeout()

setTimeout函数用来指定某个函数或某段代码,在多少毫秒后执行(只执行一次)

语法:

var timeoutld = setTimeout(func|code,delay)

timeoutld:定时器id 可以用于销毁这个定时器

func:用来延期执行的函数 可以在括号外定义或在定时器里面写

code:用来延期执行的代码

delay:延期执行多少毫秒

实例:

console.log(1) 

setTimeout(console.log(2),1000)

console.log(3)

// 1

// 3

// 2

console.log(1)

var f = function(){

        console.log(2)

}

console.log(3)

setTimeout(f,1000)

// 1

// 3

// 2

有一个需要注意的地方 如果调用的函数是对象的内部方法 那么this指向全局而不是对象的内部数据

var x = 1;

var obj = function()){

x:2,

y:function(){

console.log(this.x)

}

}

setTimeout(obj.y,1000)

// 1

由于匿名函数在全局作用域中执行,所以他指向的是全局变量中的x

解决办法:

1.在函数内部执行obj.y

var x = 1;

var obj = {

   x:2,

   y:function(){

       console.log(this.x)

   }

}

setTimeout(function(){obj.y()},1000)

// 2 

2.使用bind方法 把obj.y绑定到obj上面

var x = 1;

var obj = {

   x:2,

   y:function(){

       console.log(this.x)

   }

}

setTimeout(obj.y.bind(obj),1000)

// 2 

setInterval ()

setInterval 函数用来指定某个函数或某段代码,在多少毫秒后执行(无限次执行)

var x = 2;

setTimeout(function(){x++},1000)

console..log(x) // 3

console..log(x) // 4

clearTimeout(),clearInterval()

clearTimeout,clearInterval都用来清除定时器

var f = function(){console.log(1)}

var clear1 = setTimeout(f,1000)

var clear2 = setInterval(f,1000)

clearTimeout(clear1)

clearInterval(clear2)

防抖和节流

函数防抖debounce是指函数在某段时间内,无论触发了多少次回调,都只执行最后一次

为什么要用防抖函数呢,举个例子

有一个场景 用户在搜索框输入拼音的时候 搜索框会出现智能匹配 但是呢 用户清除一个字母在输入一个字母 会造成不必要的性能浪费(函数多次执行)

html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

    <!-- 引入样式 -->

    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">

</head>

<body>

    <input type="text" id="input" placeholder="请输入内容"/>

</body> 

</html>

js

var input = document.getElementById("input")

var output = function(){

     console.log(1)

}

input.addEventListener('keydown',output)

没有使用防抖函数的场景

从上面可以看出 函数前前后后执行了8次 然而却没输入数据进去

第一版

 var input = document.getElementById("input")

 var output = function(){

     console.log(1)

 }

 var debounce = function(func,wait){

     let timeout; //定义一个定时器

     return function(){

         clearTimeout(timeout) //清除之前的定时器

         timeout = setTimeout(func,wait) //设置定时器,延迟执行函数

     }

 }

 input.addEventListener('keydown',debounce(output,1000))

上面的思路是监听键盘的按键,每当按下键盘时,隔1秒在执行函数。当用户不断输入时,都会取消掉之前设置的定时器而重新设置,这样就保证了只有最后一次操作才能触发

现在遇到了一个问题 如何通过this来获取当前对象的值呢?

先输出一下this的值

 var debounce = function(func,wait){

     let timeout;

     return function(){

         clearTimeout(timeout)

         timeout = setTimeout(func,wait)

         console.log(this)

     }

 }

var output = function(){

     console.log(this)

 }

当前this的指向

可以看到 一个this指向了全局对象 一个this指向了当前的元素 如何更改呢?

可以使用call方法来绑定this指针

var output = function(){

     console.log(this.value)

 }

 var debounce = function(func,wait){

     let timeout;

     return function(){

         var _this = this;

         clearTimeout(timeout)

         timeout = setTimeout(function(){

             func.call(_this)

         },wait) 

     }

 }

当前this的值

这里通过了Function.prototype.call()的方法改变了this的指向问题,可以获取到当前输入的值了。现在我们再来优化一下

<script src="pinyin_dict_notone.js" type="text/javascript"></script>//文字转换拼音

<script src="pinyinUtil.js"  type="text/javascript"></script> //文字转换拼音 

var input = document.getElementById("input")

 var result = ['张三','李四','王五']

 var resultpinyin = [];

 var pinyin = function(){

    for(var i=0;i<result.length;i++){

        var split = pinyinUtil.getPinyin(result[i]).replace(" ","")

        resultpinyin.push(split)

    }

 }

 var output = function(){

    var parent = document.getElementsByClassName('result')[0].children[0]

    parent.innerHTML = ""

    var value = pinyinUtil.getPinyin(this.value).replace(" ","")

    for(var i=0;i<resultpinyin.length;i++){

        if(value[0] == resultpinyin[i][0] && resultpinyin[i].indexOf(value) != -1){

            var li = document.createElement('li')

            li.innerHTML = result[i]

            var parent =  document.getElementsByClassName('result')[0].children[0]

            parent.append(li)

            var _this = this

            li.addEventListener('click',function(){

                input.value = this.innerText

                parent.innerHTML = ""

            })

        }

    }

 }

 var debounce = function(func,wait){

     let timeout;

     return function(){

         var _this = this;

         clearTimeout(timeout)

         timeout = setTimeout(function(){

             func.call(_this)

         },wait) 

     }

 }

pinyin()    

input.addEventListener('keydown',debounce(output,1000))

现在让我们来看一下节流函数 什么是节流呢?

如果某个事件持续触发,隔一段时间内,事件才会执行一次

让我们看个场景 现在许多网站有个返回顶部的功能 以简书为例

返回顶部

现在 我们来考虑一下这个功能该如何实现呢?

首先呢  先输出一下当前浏览的位置

var scrollTop = document.body.scrollTop ||document.documentElement.scrollTop;

当浏览器滑动的时候 添加一个函数

function show(){

    var scrollTop = document.body.scrollTop ||document.documentElement.scrollTop;  

    console.log(scrollTop)

}

window.onscroll = show

有个问题是 浏览器滚动时 函数执行频率太高了 这样很浪费性能 这时候 我们可以用节流函数来做优化

节流函数有两种方式实现:时间戳和定时器

第一版

时间戳

html

<body>

    <div style="height: 2000px;"></div>

    <div class="top">

        回到顶部

    </div>

</body>

function show(scroll){

        if(scroll > 500){

            document.getElementsByClassName('top')[0].style.display = "block"

        }else{

            document.getElementsByClassName('top')[0].style.display = "none"

        }

        console.log(scroll)

    }

    function throttle(func,wait){

        var previous = 0;

        return function(){

            var nowtime = +new Date()

            if(nowtime - previous > wait){ //判断一下触发事件的时候是否大于设定的时间周期

                var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

                show(scrollTop)

                previous = nowtime

            }

        }

    }

    window.addEventListener('scroll',throttle(show,500))

这里使用了时间戳的方法,第一次滚动时函数会立马执行,当滚动停止后没有办法在执行事件

未滚动前 滚动后

可以看到 只执行了一次事件 现在看看定时器

function throttle(func,wait){

        var time;

        var previous = 0;

        return function(){

            if(!time){ //判断定时器是否存在

                time = setTimeout(function(){ //设置定时器

                    time = null //清空定时器 直到下一次执行

                    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

                    func(scrollTop)

                },wait)

            }

        }

滚动后

可以看到 当滚动了一段距离后 函数才会执行一次 。

有没有一种办法 既能让函数在第一次滚动的时候马上执行 在滚动完后也开始执行呢?

function throttle(func,wait){

        var time,scrollTop;

        var previous = 0;

        var start = function(scrollTop){

            previous = +new Date()

            time = null;

            func(scrollTop)

        }

        return function(){

            var now = +new Date()

            //下次触发func的时间

            var remaining = wait - (now - previous)

            scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

            //如果没有剩余的时间了

            if(remaining <= 0 || remaining > wait){

                if(time){

                    clearTimeout(time)

                    time = null;

                }

                previous = now;

                func(scrollTop)

            }else if(!time){

                time = setTimeout(start,remaining)

            }

        }  

    }

这里判断一下上次执行的时间和这次触发的时间是否大于执行周期,如果大于则判断定时器是否存在,存在则清除之前设置的定时器,重新设置。

回到顶部功能

var backTop = document.getElementsByClassName('top')[0]

    backTop.addEventListener('click',function(){

        window.scrollTo(0,0);  

    })

参考链接

https://wangdoc.com/javascript/async/timer.html

https://www.javascriptc.com/2283.html

https://www.javascriptc.com/2285.html

相关文章

  • js字符串,定时器

    Javascript组成 字符串处理方法: 定时器在javascript中的作用: 定时器: setTimeout...

  • JavaScript

    javascript引入方式 定时器

  • 「DOM 编程」JavaScript 动画

    JavaScript 动画实现方式JavaScript 动画三要素定时器常见动画动画函数 JavaScript 动...

  • 驯服定时器和线程

    定时器并不属于JavaScript 虽然我们一直在JavaScript中使用定时器,但是它并不是javascrip...

  • 定时器 类型转换 封闭函数

    定时器定时器在javascript中的作用1、制作动画2、异步操作3、函数缓冲与节流 定时器类型及语法 /*定时器...

  • 定时器

    定时器定时器在javascript中的作用1、制作动画2、异步操作3、函数缓冲与节流定时器类型及语法/*定时器:s...

  • Web26.闭包&定时器&BOM

    定时器 JavaScript提供执行代码的功能,叫做定时器(timer),主要由setTimeout()和setI...

  • 定时器

    定时器 JavaScript提供定时执行代码的功能,叫做定时器,主要由setTimeout()和setInterv...

  • 2018-07-09

    定时器在javascript中的作用 1、制作动画 2、异步操作 3、函数缓冲与节流 定时器类型及语法 定时器: ...

  • 定时器

    定时器 定时器在javascript中的作用 1、制作动画 2、异步操作 3、函数缓冲与节流 定时器类型及语法 /...

网友评论

      本文标题:Javascript定时器

      本文链接:https://www.haomeiwen.com/subject/isjdmhtx.html