事件轮询机制

news2024/10/11 20:35:21

引出闭包案例

for(var i = 0; i < 5; i++) {
    setTimeout(function () {
      console.log(i); // ?
    });
}
console.log('a');
// 结果是什么:?

2.事件轮询机制(Event Loop)

事件轮询(Event Loop)是一个很重要的概念,指的是计算机系统的一种运行机制。JavaScript语言就是采用的这种机制,来解决单线程运行带来的一些问题。

  1. 同步和异步任务分别进入不通的执行“场所”,同步的进入主线程,异步的进入Event Table并注册函数

  2. 当指定的事情完成时,Event Table会将这个函数移入Event Queue(事件队列/任务队列/消息队列)

  3. 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行

  4. 上述过程会不断重复,也就是常说的Event loop(事件循环)

进程:

  • 进程是指在系统中正在运行的一个应用程序,程序一旦运行就是进程。

  • 一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。

线程:

  • 线程是进程的一个实体,是进程的一条执行路径。

  • 线程是CPU独立运行和独立调度的基本单位。

任务队列:

  • 将要被执行的任务,存放在浏览器的任务队列中

单线程:

  • 每次只能干一件事

多线程:

  • 多线程是指从软件或者硬件上实现多个线程的并发技术

  • 优势:

    • 使用多线程可以把程序中占据时间长的任务放到后台去处理,如图片、视屏的下载

    • 发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好

举例:你早上上班,正要打卡的时候,手机响了。。你如果先接了电话,等接完了,在打卡,就是单线程。 如果你一手接电话,一手打卡, 就是多线程。 2件事的结果是一样的。。你接了电话且打了卡。

事件轮询:

  • 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)

2.1 JS是单线程还是多线程

javaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。 为什么不允许js可以实现多线程?因为如果实现了多线程,一个线程创建了一个div元素,而另外一个线程删除了这个div元素,那么这个时候浏览器应该听谁的? 所以为了避免出现这种互相冲突的操作,js从一开始就是单线程的,这就是它的核心特征。 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

2.2 任务队列

2.2.1 什么是宏任务,什么是微任务

在js的异步任务中,分为宏任务和微任务

宏任务(由宿主也就是浏览器和node引发): setTimeout,setInterval,Ajax(网络请求),DOM事件

微任务(js引擎发布的任务): Promise async/await promise本身是同步的,then/catch的回调函数是异步的

注意:微任务比宏任务的执行时间要早

2.2.2 宏任务和微任务的执行顺序
  1. 同步代码

  2. 微任务的异步代码(promise等)

  3. 宏任务的异步代码(setTimeout,setInterval等)

执行顺序

 

2.2.3 案例
console.log(1);
setTimeout(function(){
    console.log(2);
},100)
let pro = new Promise((resolve,reject)=>{
    console.log(3)
    resolve(1000);
    console.log(4)
})
pro.then(data=>{
    console.log(data);
})
console.log(5); // 1 3 4 5 1000 2

2.3 解决方案

  1. 使用闭包

for(var i = 0; i < 5; i++) {
  //这个匿名函数生成了闭包的效果,新建了一个作用域,这个作用域接收到每次循环的i值保存了下来,即使循环结束,闭包形成的作用域也不会被销毁
  (function(i) {
      setTimeout(function () {
          console.log(i);
      });
  })(i)
}
console.log('a');
  1. 使用let变量

for(let i = 0; i < 5; i++) {
  setTimeout(function () {
      console.log(i);
  });
}

3.闭包

特性:

  1. 函数嵌套函数

  2. 函数内部可以引用函数外部的参数和变量

  3. 参数和变量不会被垃圾回收机制回收【延长变量作用域】

闭包是js开发惯用的技巧:能够访问另一个函数作用域的变量的函数

清晰的讲:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量 闭包可以用在许多地方。它的最大用处有两个

  1. 一个是前面提到的可以读取函数内部的变量

  2. 另一个就是让这些变量的值始终保持在内存中。

function func1(){
    var num = 1;
    function func2(){
        return num;
    }
    return func2; // 闭包
}
var num = func1()();
console.log(num);

注意:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

3.1 闭包的作用

闭包可以延长作用域链

function person(name){
    var name = name;
    function sayName(){
      console.log(name)
    }
    return sayName;
}
var fun = person('王小明');
fun();// 王小明

fun 是一个 全局函数,但可以访问到person里的局部变量 name,这是因为fun的值是从person函数中返回的sayName函数,而sayName 函数是可以访问到局部变量 name 的;

3.2 复杂闭包案例分析

function outer(){
  // 局部变量
  var a = '我是outer里面的变量';
  // var c = 'one'
  // console.log(a);
  function twoinner(){
    var b = '我是twoinner的变量';
    var c = 'two'
    // console.log(b);
    return a;
    // function thrinner(){
    //     var c = '我是thrinner';
    //     console.log(c);
    // }
    // thrinner();
    // return thrinner;
  }
  return twoinner; // 函数体: twoinner函数就是一个闭包, 因为它能够访问到其他函数中的变量的作用域
}
// console.log(outer());
// console.log(outer()());
// outer()()();
var n =  outer()();
console.log(n);

3.3 闭包能够解决的问题

问题:给下面5个li添加点击事件,点击显示当前元素的下标

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
<script>
  var oli = document.getElementsByTagName('li');
    /* 输出的全都是5 */
    for(var i=0;i<oli.length;i++){
        oli[i].onclick = function(){
            console.log(i);
        }
    } 
</script>

使用闭包解决

/* 闭包方案解决: */
for(var i=0;i<oli.length;i++){
  oli[i].onclick = (function(i){
    return function(){
      console.log(i);
    }
  })(i); // 闭包
}

使用let解决

// let 方案解决
for(let i=0;i<oli.length;i++){
  oli[i].onclick = function(){
    console.log(i);
  }; // 闭包
}

分析执行过程

/* 分析执行过程 */
oli[0].onclick = (function(0){
  return function(){
    console.log(0);
  }
})(0);
// => 第一次循环 闭包函数自执行完毕
oli[0].onclick = function(){
  console.log(0);
};

3.4 闭包有三个特性:

  1. 函数嵌套函数

  2. 函数内部可以引用外部的参数和变量

  3. 参数和变量不会被垃圾回收机制回收

  4. 自执行函数

(function a(){alert('我是自执行函数')} ()); // 用括号把整个表达式包起来
(function a(){alert('我是自执行函数')}) (); //用括号把函数包起来
!function a(){alert('我是自执行函数')}(); // 求反,我们不在意值是多少,只想通过语法检查。
+function a(){alert('我是自执行函数')}();
-function a(){alert('我是自执行函数')}();
~function a(){alert('我是自执行函数')}();
void function a(){alert('我是自执行函数')}();
new function a(){alert('我是自执行函数')}();

自执行函数通常都是定义之后立即执行,以后都不再会调用,所以声明时可以省略函数名,因此自执行函数又叫匿名函数

(function(){console.log('我是匿名函数')})();// 我是匿名函数

如果上一行代码没有使用 分号 ' ; '结束,可能会导致匿名函数通不过语法检查,所以通常会在小括号前加个分号

;(function(){console.log('我是匿名函数')})()// 我是匿名函数

4.1自执行函数的效果

自执行函数可以用来保存变量的作用域,防止污染全局变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2205784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

调整ApplyItem的界面

调整ApplyItem的界面 前言 在上一集&#xff0c;我们就完成了一个clickItem的一个函数&#xff0c;继承SessionFriendItem并通过它添加不同的Item&#xff0c;并且我添加了它的枚举类。 在上一集的最后&#xff0c;我们提了一嘴&#xff0c;我们要修改ApplyItem的样式。 分…

Flink 04 | 窗口介绍 - 无界数据流的核心

窗口介绍 Flink中Windows&#xff08;窗口&#xff09;是处理无界数据流的核心。因为无界数据集是不断增长的&#xff0c;无法直接对整个数据集进行操作。窗口将数据流分成有限大小的Buckets&#xff0c;我们可以在这些Buckets上应用计算。本文档重点介绍如何在 Flink 中选择合…

三菱FX3UPLC机械原点回归- DSZR/ZRN指令

机械原点回归用指令的种类 产生正转脉冲或者反转脉冲后&#xff0c;增减当前值寄存器的内容。可编程控制器的定位指令&#xff0c;可编程控制器的电源0FF后&#xff0c;当前值寄存器清零&#xff0c;因此上电后&#xff0c;请务必使机械位置和当前值寄存器的位置相吻合…

10.模拟实现s

前面我们了解了string类的常用接口使用&#xff0c;那么现在就来模拟实现一下。 1.constructor string.h namespace Ro {class string{public:string(){}string(const char* str){}~string(){}private:char* _str;size_t _size;size_t _capacity;}; } 为了和库里面的string…

Jenkins+kubernetes流水线构建java项目

在传统的业务环境中&#xff0c;我们的应用部署或者更新都是采用手工的方式&#xff0c;但是在企业内部&#xff0c;应用架构一般都采用微服务&#xff0c;大部分项目都会对应几十个、上百甚至上千个微服务&#xff0c;并且还不仅仅只有一个项目&#xff0c;所以采用收工方式上…

godot帧同步-关于“显示与逻辑分离”

很多教程说帧同步的关键是“显示与逻辑分离”&#xff0c;但是又没有具体讲解&#xff0c;我起初也没有搞懂这句话的意思&#xff0c;就直接上手开发帧同步了。在开发的过程中&#xff0c;一下子就悟了&#xff0c;所以分享一下。 显示与逻辑未分离&#xff08;单机&#xff0…

嵌入式中单链表基本实现

第一:单链表基本原理 依次读入表L=(a0,.....,an-1)中每一元素ai(假设为整型),若ai≠结束符(-1),则为ai创建一结点,然后插入表尾,最后返回链表的头结点指针H。 第二:单链表具体实现方法 1:实现单链表的时候,需要先定义基本文件link.h #ifndef __LINKLIST_H__ #define…

考华为认证拼了命,怎么还是没工作啊

在当今竞争激烈的就业市场中&#xff0c;网络工程领域的发展备受关注。当你疯狂地在某 BOSS 或者某联等招聘平台上浏览时&#xff0c;你必然会惊讶地发现&#xff0c;华为认证已赫然成为网络方向至关重要的资格认证之一&#xff0c;频繁地出现在形形色色的岗位 JD 里。 这一现…

如何设置 GitLab 密码长度?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 60天专业…

【RabbitMQ——消息应答机制——分布式事务解决方式】

1. RabbitMQ高级-消息确认机制的配置 NONE值是禁用发布确认模式&#xff0c;是默认值 CORRELATED值是发布消息成功到交换器后会触发回调方法&#xff0c;如1示例SIMPLE值经测试有两种效果&#xff0c;其一效果和CORRELATED值一样会触发回调方法&#xff0c;其二在发布消息成功…

UE5 TimeLine入门

UE5 TimeLine入门 时间轴曲线 共计三个关键帧&#xff08;0,0&#xff09;(1.5,10) (3,0) 蓝图 1.按下空格键执行。 2.时间轴TimeLine函数。 3.动画播放结束后执行。 4.每一帧都执行。

GR-ConvNet论文 学习笔记

GR-ConvNet 文章目录 GR-ConvNet前言一、引言二、相关研究三、问题阐述四、方法A.推理模块B.控制模块C.模型结构D.训练方法E.损失函数 五、评估A.数据集B.抓取评判标准 六、实验A.设置B.家庭测试物体C.对抗性测试物体D.混合物体 七、结果A.康奈尔数据集B.Jacquard数据集C.抓取新…

Java—继承性与多态性

目录 一、this关键字 1. 理解this 2. this练习 二、继承性 2.1 继承性的理解 2.1.1 多层继承 2.2 继承性的使用练习 2.2.1 练习1 2.2.2 练习2 2.3 方法的重写 2.4 super关键字 2.4.1 子类对象实例化 三、多态性 3.1 多态性的理解 3.2 向下转型与多态练习 四、Ob…

使用node.js控制CMD命令——修改本机IP地址

设置每次打开cmd命令行窗口都是以管理员身份运行&#xff1a; 1. 按下Ctrl Shift Esc键组合&#xff0c;打开任务管理器。 2. 在任务管理器中&#xff0c;点击“文件”菜单&#xff0c;选择“运行新任务”。 3. 在“创建新任务”对话框中&#xff0c;输入cmd&#xff0c;勾…

无人机之信息管理系统篇

一、系统概述 无人机信息管理系统通过整合软件和硬件设备&#xff0c;实现对无人机的全面监控、管理、调度和数据分析。它能够帮助用户实时掌握无人机的飞行状态、位置信息等重要数据&#xff0c;确保飞行安全和隐私保护。 二、系统组成 无人机信息管理系统通常由以下几个关键…

达梦8-SQL日志配置与分析工具

以 dmsql_数据库实例名.log 类型命名的文件为跟踪日志文件&#xff0c;跟踪日志内容包含系统各会话执行的 SQL 语句、参数信息、错误信息等。跟踪日志主要用于分析错误和分析性能问题&#xff0c;比如&#xff0c;可以挑出系统现在执行速度较慢的 SQL 语句&#xff0c;进而对其…

React学习过程(持续更新......)

React学习过程&#xff08;持续更新…&#xff09; 创建react的hello项目 使用node创建create-react-app脚手架项目 //首先你得先安装node&#xff0c;这里不做详细教程&#xff0c;我使用的node为20.18.0 npm isntall create-react-app -g //全局安装create-react-app crea…

Web安全常用工具 (持续更新)

前言 本文虽然是讲web相关工具&#xff0c;但在在安全领域&#xff0c;没有人是先精通工具&#xff0c;再上手做事的。鉴于web领域繁杂戎多的知识点&#xff08;工具是学不完的&#xff0c;哭&#xff09;&#xff0c;如果你在本文的学习过程中遇到没有学过的知识点&#xff0…

【笔记】Day2.3.2数据校验

此项目中有两种数据校验方式 1.hibernate-validated注解方式 在controller头上开启数据校验模式需要加入Validated 然后就可以 在参数前面加入任意的数据校验里的注解 例如;:NotNull() NotEmpty()等 面对字符串型的数据校验 参数前可以使用NotBlank()等 而面对对象/DTO实体的…

mongodb GUI工具(NoSQLBooster)

介绍 跨平台的MongoDB GUI工具&#xff0c;支持Windows、macOS和Linux。自带服务器监控工具、Visual Explain Plan、查询构建器、SQL查询等功能。提供免费版本&#xff0c;但功能相比付费版本有所限制。 免费版可供个人/商业使用&#xff0c;但功能有限。 安装成功后&#x…