js引擎的工作原理、、js是事件的eventloop、、宏任务源tasks和微任务源jobs、、js构造抽象语法书(AST)

js引擎只执行同步任务, 异步任务会有工作线程来执行,当需要进行异步操作(定时器、ajax请求、dom事件注册等), 主线程会发一个异步任务的请求, 相应的工作线程接受请求; 当工作线程完成工作之后, 通知主线程;主线程接收到通知之后, 会执行一定的操作(回调函数)。主线程和工作线程之间的通知机制叫做事件循环。

调用栈 (call stack): 主线程执行时生成的调用栈
任务队列 (task queue): 工作线程完成任务后会把消息推到一个任务队列, 消息就是注册时的回调函数
在这里插入图片描述

当调用栈为空时, 主线程会从任务队列里取一条消息并放入当前的调用栈当中执行, 主线程会一直重复这个动作直到消息队列为空。 这个过程就叫做事件循环 (event-loop)。

关于宏任务和微任务,参考 事件流、事件模型、事件循环概念理解? 浏览器线程理解与microtask与macrotask

ES6新引入了Promise标准,同时浏览器实现上多了一个microtask微任务概念。在ECMAScript中,microtask称为jobs,macrotask可称为task。

macrotask宏任务tasks,也就是上面说到的任务队列的任务。执行栈上的每个任务都属于宏任务,主线程执行完执行栈的任务,从任务队列取新的任务。宏任务执行时不会中断,会一次性执行完,为了及时渲染数据,主线程执行完一个宏任务之后,会执行一次渲染。
task–》渲染 --》宏任务 --》渲染 …

microtask微任务jobs,可以看成是插队需要及时处理的任务,会在当前主线程task任务执行后,渲染线程渲染之前,执行完当前积累所有的微任务。
task–》jobs --》渲染 --》宏任务 --》jobs --》渲染 …

AST 参考:程序语言进阶之DSL与AST实战解析

将抽象语法树之前要先了解下NLP中文法的概率。任何一种语言,具体说就是DSL,都有自己的一套文法,用来表示这套语言的逻辑规范。不同的文法写出来的语法表达式也不一样。我们根据语法表达式来解析语言,就可以形成一个AST抽象语法树。然后可以作进一步处理。我常用的是PEG解析表达式语法。可以很轻松的写出语法的每一条产生式规则,来构造生成AST。所谓AST可以理解成按照一定语法结构组成的词汇流,每个词汇有特定的语法含义,比如说这是一个声明,这个一个操作符等等。
在这里插入图片描述

上面这个图是苹果最早做的KHTML渲染引擎中的KJS(javascript引擎),他是基于AST来实现的JavaScript语言解析的,先通过词法分析得到JSTokens流,然后经过语法分析得到抽象语法树,然后经过字节码生成器,转换成字节码。字节码经过JavaScript虚拟机JIT编译成机器码,然后执行。这是最初的设计架构,后来苹果公司基于此重构出了webkit渲染引擎,google基于webkit单独维护,称为blink渲染引擎,chrome的JS引擎改造为V8引擎。参考:简述Chromium, CEF, Webkit, JavaScriptCore, V8, Blink

举个例子常用的babel插件的原理就是基于babylon词法语法分析器生成抽象语法树,将代码文本转换成按照特定语法组合的token流集合,然后经过babtlon-traverse这个组件来负责处理遍历语法树,访问每个token节点,通过对token的处理,可以生成我们需要的AST语法树,然后再通过babylon-generator这个组件来做代码生成,根据AST生成代码。比如可以将 箭头函数 转换成 function函数。

浏览器中,通过开发者调试工具分析就能看到,下载完js脚本后,首先浏览器要先解析代码=》初始化上下文环境=》执行代码,整个是evaluate script的过程,解析代码的过程也是编译js的过程所以看最前面第一步就是compile script,将js代码编译成字节码(这一块涉及到浏览器js引擎的优化,v8引擎是编译成字节码,后面经过JIT解析执行(这个参考 你不知道的LLVM编译器 可以提升效率做动态优化), 这个类似于java、C#这些需要将源代码编译成中间语言,然后在虚拟机执行,javascript编译成字节码后面也是在虚拟机执行),然后就开始执行脚本。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!要实现页面展示所有任务链接并且能够新建任务,您可以使用以下的JavaScript代码: 首先,您需要一个用于展示任务的HTML元素,比如一个列表(`<ul>`)和一个输入框(`<input>`): ```html <ul id="taskList"></ul> <input type="text" id="newTaskInput"> <button onclick="addNewTask()">添加任务</button> ``` 然后,在JavaScript中,您可以使用一个数组来保存所有的任务: ```javascript var tasks = []; ``` 接下来,您可以编写一个用于展示所有任务的函数,该函数会遍历任务数组,并将每个任务作为链接添加到列表中: ```javascript function displayTasks() { var taskList = document.getElementById("taskList"); taskList.innerHTML = ""; // 清空列表 for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; var listItem = document.createElement("li"); var link = document.createElement("a"); link.href = task.url; link.textContent = task.name; listItem.appendChild(link); taskList.appendChild(listItem); } } ``` 然后,您可以编写一个函数来添加新任务。该函数将获取输入框中的值,并将其添加到任务数组中,然后调用`displayTasks()`函数来更新任务列表: ```javascript function addNewTask() { var newTaskInput = document.getElementById("newTaskInput"); var newTaskName = newTaskInput.value; if (newTaskName !== "") { var newTask = { name: newTaskName, url: "#" // 这里将url设置为#,您可以根据需求修改 }; tasks.push(newTask); displayTasks(); newTaskInput.value = ""; // 清空输入框 } } ``` 现在,当用户在输入框中输入新的任务名称并点击“添加任务”按钮时,新任务将被添加到任务数组中,并且任务列表将被更新。 请注意,上述代码仅为示例,您可能需要根据您的实际需求进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值