百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

如何理解JavaScript定时器的4种写法「带面试题讲解」

toyiye 2024-07-03 01:59 19 浏览 0 评论

在JavaScript里,我们已经会使用一些原生提供的方法来实现需要延时执行的操作代码,比如很多在线时钟的制作,图片轮播的实现,还有一些广告弹窗,但凡可以自动执行的东西,都是可以和定时器有关的。今天就来和大家分享一下,关于我们在JavaScript里经常会使用到的定时器方法

在JavaScript里,我们要学习四个定时器的使用方法,setTiemout、setInterval、setImmediate、requestAnimationFrame,一起来看看吧!


什么是定时器

JavaScript中提供了一些原生的函数方法来实现延时去执行某一段代码,这个就是定时器

下面我们来认识一下这些定时器

setTimeout:

设置一个定时器,在定时器到期后执行一次函数或代码段

 var timeoutId = window.setTimeout(func[, delay,param1,...]);
 var timeoutId = window.setTimeout(code[, delay]);

上面用到的关键词名称的意义:

timeoutId: 定时器ID

func: 延迟后执行的函数

code: 延迟后执行的代码字符串,不推荐使用原理类似eval()

delay: 延迟的时间(单位:毫秒),默认值为0

param1: 向延迟函数传递而外的参数,IE9以上支持

setInterval:

以固定的时间间隔重复调用一个函数或者代码段

 var intervalId = window.setInterval(func, delay[, param1,...]);
 var intervalId = window.setInterval(code, delay);

intervalId: 重复操作的ID

func: 延迟调用的函数

code: 代码段

delay: 延迟时间,没有默认值

setImmediate:

在浏览器完全结束当前运行的操作之后立即执行指定的函数(仅IE10和Node 0.10+中有实现),类似setTimeout(func, 0)

 var immediateId = setImmediate(func[, param1, param2, ...]);
 var immediateId = setImmediate(func);

immediateId: 定时器ID

func: 回调

requestAnimationFrame:

专门为实现高性能的帧动画而设计的API,但是不能指定延迟时间,而是根据浏览器的刷新频率而定(帧)

 var requestId = window.requestAnimationFrame(func);

func: 回调


举几个栗子加深思考


基本用法

 // 下面代码执行之后会输出什么?
 var intervalId, timeoutId;
 timeoutId = setTimeout(function() {
    console.log(1);
 }, 300);
 setTimeout(function() {
 clearTimeout(timeoutId);
     console.log(2);
 }, 100);
 setTimeout('console.log("5")', 400);
 intervalId = setInterval(function() {
     console.log(4);
 clearInterval(intervalId);
 }, 200);
 // 分别输出: 2、4、5

setInterval 和 setTimeout的区别?

// 执行下面的代码块会输出什么?
 setTimeout(function() {
    console.log('timeout');
 }, 1000);
 setInterval(function() {
    console.log('interval')
 }, 1000);
 // 输出一次 timeout,每隔1S输出一次 interval
 /*--------------------------------*/
 // 通过setTimeout模拟setInterval 和 setInterval有啥区别么?
 varcallback = function() {
 if(times++ > max) {
 clearTimeout(timeoutId);
 clearInterval(intervalId);
 }
     console.log('start', Date.now() - start);
 for(var i = 0; i < 990000000; i++) {}
    console.log('end', Date.now() - start);
 },
 delay = 100,
 times = 0,
 max = 5,
 start = Date.now(),
 intervalId, timeoutId;
 functionimitateInterval(fn, delay) {
    timeoutId = setTimeout(function() {
 fn();
 if(times <= max) {
 imitateInterval(fn ,delay);
 }
 }, delay);
 }
 imitateInterval(callback, delay);
 intervalId = setInterval(callback, delay);


如果是setTimeout和setInterval的话,它俩仅仅在执行次数上有区别,setTimeout一次、setIntervaln次。

而通过setTimeout模拟的setInterval与setInterval的区别则在于:setTimeout只有在回调完成之后才会去调用下一次定时器,而setInterval则不管回调函数的执行情况,当到达规定时间就会在事件队列中插入一个执行回调的事件,所以在选择定时器的方式时需要考虑setInterval的这种特性是否会对你的业务代码有什么影响?


setTimeout(func, 0) 和 setImmediate(func)谁更快?

 console.time('immediate');
 console.time('timeout');
 setImmediate(() => {
     console.timeEnd('immediate');
 });
 setTimeout(() => {
     console.timeEnd('timeout');
 }, 0);

在Node.JS v6.7.0中测试发现setTimeout更早执行


几道经典的定时器面试题

下面代码运行后的结果是什么?

 // 题目一
 var t = true;
 
 setTimeout(function(){
    t = false;
 }, 1000);
 
 while(t){}
 
 alert('end');

 // 题目二
 for(var i = 0; i < 5; i++) {
 setTimeout(function() {
        console.log(i);
 }, 0);
 }
 
 // 题目三
 var obj = {
    msg: 'obj',
 shout: function() {
 alert(this.msg);
 },
 waitAndShout: function() {
 setTimeout(function() {
 this.shout();
 }, 0);
 }
 };
 obj.waitAndShout();

在讲解上面面试题的答案之前,我们先要理解一下定时器的工作原理,以方便理解上面的题目


JS定时器的工作原理

这里将用引用How JavaScript Timers Work中的例子来解释定时器的工作原理,该图为一个简单版的原理图。

在这图中,左侧数字代表时间,单位毫秒;

左侧文字代表某一个操作完成后,浏览器去询问当前队列中存在哪些正在等待执行的操作;

蓝色方块表示正在执行的代码块;

右侧文字代表在代码运行过程中,出现哪些异步事件。

大致流程如下:

1.程序开始时,有一个JS代码块开始执行,执行时长约为18ms,在执行过程中有3个异步事件触发,其中包括一个setTimeout、鼠标点击事件、setInterval

2.第一个setTimeout先运行,延迟时间为10ms,稍后鼠标事件出现,浏览器在事件队列中插入点击的回调函数,稍后setInterval运行,10ms到达之后,setTimeout向事件队列中插入setTimeout的回调

当第一个代码块执行完成后,浏览器查看队列中有哪些事件在等待,他取出排在队列最前面的代码来执行

3.在浏览器处理鼠标点击回调时,setInterval再次检查到到达延迟时间,他将再次向事件队列中插入一个interval的回调,以后每隔指定的延迟时间之后都会向队列中插入一个回调

4.后面浏览器将在执行完当前队头的代码之后,将再次取出目前队头的事件来执行

在这也只是对定时器的工作原理做了简单的叙述,其实实际的实现处理过程会更加复杂。


面试题的答案

在我们理解了定时器的运行原理之后,接下来我们就基于运行原理的基础上,来看看上面的经典面试题的答案

第一题

alert永远都不会执行,因为JS是单线程的,且定时器的回调将在等待当前正在执行的任务完成后才执行,而while(t) {}直接就进入了死循环一直占用线程,不给回调函数执行机会

第二题

代码会输出 5 5 5 5 5,理由同上,当i = 0时,生成一个定时器,将回调插入到事件队列中,等待当前队列中无任务执行时立即执行,而此时for循环正在执行,所以回调被搁置。当for循环执行完成后,队列中存在着5个回调函数,他们的都将执行console.log(i)的操作,因为当前JS代码上中并没有使用块级作用域,所以i的值在for循环结束后一直为5,所以代码将输出5个5

第三题

这个问题涉及到this的指向问题,由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. 这会导致这些代码中包含的this关键字会指向window (或全局)对象,window对象中并不存在shout方法,所以就会报错,修改方案如下:

 var obj = {
     msg: 'obj',
 shout: function() {
 alert(this.msg);
 },
 waitAndShout: function() {
 var self = this; // 这里将this赋给一个变量
 setTimeout(function() {
            self.shout();
 }, 0);
 }
 };
 obj.waitAndShout();

需要注意的点

1.setTimeout有最小时间间隔限制,HTML5标准为4ms,小于4ms按照4ms处理,但是每个浏览器实现的最小间隔都不同

2.因为JS引擎只有一个线程,所以它将会强制异步事件排队执行

3.如果setInterval的回调执行时间长于指定的延迟,setInterval将无间隔的一个接一个执行

4.this的指向问题可以通过bind函数、定义变量、箭头函数的方式来解决

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码