常见的浏览器内核
浏览器/RunTime
内核(渲染引擎)
JavaScript 引擎
Chrome
Blink(28~) Webkit(Chrome 27)
V8
FireFox
Gecko
SpiderMonkey
Safari
Webkit
JavaScriptCore
Edge
EdgeHTML
Chakra(for JavaScript)
IE
Trident
Chakra(for JScript)
PhantomJS
Webkit
JavaScriptCore
Node.js
--
V8
浏览器的主要组成部分
用户界面 - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
呈现引擎 - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
浏览器引擎- 在用户界面和呈现引擎之间传送指令。
网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
JavaScript 解释器 - 用于解析和执行 JavaScript 代码。
数据存储 - 这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。
浏览器是如何渲染UI的?
浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree
与此同时,进行CSS解析,生成Style Rules
接着将DOM Tree与Style Rules合成为 Render Tree
接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标
随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来
什么是JavaScript解析引擎?
简单地说,JavaScript解析引擎就是能够“读懂”JavaScript代码,并准确地给出代码运行结果的一段程序。比方说,当你写了 var a = 1 + 1; 这样一段代码,JavaScript引擎做的事情就是看懂(解析)你这段代码,并且将a的值变为2。
“JavaScript 引擎” 通常被称作一种虚拟机。
JavaScript 虚拟机是一种进程虚拟机,专门设计来解释和执行的 JavaScript代码。
JavaScript 引擎的基本工作是把开发人员写的 JavaScript代码转换成高效、优化的代码,这样就可以通过浏览器进行解释甚至嵌入到应用中。每个JavaScript引擎都实现了一个版本的ECMAScript,JavaScript是它的一个分支。随着ECMAScript的不断发展,JavaScript引擎也不断改进。之所以有这么多不同的引擎,是因为它们每个都被设计运行在不同的web浏览器、headless浏览器、或者像Node.js那样的运行时环境中,它的唯一的目的就是读取和编译JavaScript代码。
解析引擎就是根据ECMAScript定义的语言标准来动态执行JavaScript字符串;
解析JS的过程分成两个阶段:语法检查阶段和运行阶段;
语法检查包括词法分析和语法分析,运行阶段又包括预解析和运行阶段(V8引擎会将JavaScript字符串编译成二进制代码,此过程应该归到语法检查过程中);
在JavaScript解析过程中,如遇错误就直接跳出当前代码块,直接执行下一个script代码段。所以在同一个script内的代码段有错误的话就不会执行下去,但是不会影响下一个script内的代码段。
第一阶段:语法检查
语法检查也是JavaScript解析器的工作之一,包括词法分析 和 语法分析,过程大致如下:
一:词法分析:
JavaScript解释器先把JavaScript代码(字符串)的字符流按照ECMAScript标准转换为记号流。
a = (b - c);
复制代码
转换为记号流:
NAME "a"
EQUALS
OPEN_PARENTHESIS
NAME "b"
MINUS
NAME "c"
CLOSE_PARENTHESIS
SEMICOLON
复制代码
二:语法分析:
JavaScript语法分析器在经过词法分析后,将记号流按照ECMAScript标准把词法分析所产生的记号生成语法树。通俗地说就是把从程序中收集的信息存储到数据结构中,每取一个词法记号,就送入语法分析器进行分析。
语法分析不做的事:去掉注释,自动生成文档,提供错误位置(可以通过记录行号来提供)。
ECMAScript标准如下:
var,if,else,break,continue等是JavaScript的关键词
怎么样算是数字、怎么样算是字符串等等
定义了操作符(+,-,=)等操作符
定义了JavaScript的语法
定义了对表达式,语句等标准的处理算法,比如遇到==该如何处理
...
复制代码
当语法检查正确无误之后,就可以进入运行阶段了。
第二阶段:运行阶段
预解析
第一步:创建执行上下文。解析器将语法检查正确后生成的语法树复制到当前执行上下文中。
第二步:属性填充。解析器会对语法树当中的变量声明、函数声明以及函数的形参进行属性填充。
预解析阶段创建的执行上下文包括:变量对象、作用域链、this
变量对象(Variable Object):由vardeclaration、function declaration(变量声明、函数声明)、arguments(参数)构成。变量对象是以单例形式存在。
作用域链(Scope Chain):variableobject + all parent scopes(变量对象以及所有父级作用域)构成。
this值:(thisValue):contentobject。this值在进入上下文阶段就确定了。一旦进入执行代码阶段,this值就不会变了。
console.log(a); //function a(){console.log(4);}
var a = 1;
function a(){console.log(2);}
console.log(a);
var a = 3;
console.log(a);
function a(){console.log(4);}
console.log(a)
复制代码
第一行:会弹出functiona(){console.log(4);} ,因为预解析完成之后,被存进内存的a的值就是functiona(){console.log(4);}
第二行:第三行里有表达式,a被赋了一个新的值1表达式会改变变量的值。表达式可以改变预解析的值。
第三行:只是函数的声明,并没有用到表达式,而且也没有函数的调用,所以不会改变a的值。
第四行:因为a的值没有变化,所以还是1
第五行:使用了表达式,a被赋了一个新的值3
第六行:会弹出3
第七行:函数的声明,不会改变a的值。
第八行:a的值没有改变,所以还是3
JavaScript解析引擎与ECMAScript的关系
JavaScript引擎是一段程序,我们写的JavaScript代码也是程序,如何让程序去读懂程序呢?这就需要定义规则。比如,之前提到的var a = 1 + 1;,它表示:
左边var代表了这是申明(declaration),它申明了a这个变量
右边的+表示要将1和1做加法
中间的等号表示了这是个赋值语句
最后的分号表示这句语句结束了
标准的JavaScript引擎就会根据ECMAScript这套文档去实现,注意这里强调了标准,因为也有不按照标准来实现的,比如IE的JS引擎。这也是为什么JavaScript会有兼容性的问题。
JavaScript解析引擎与浏览器是什么关系
简单地说,JavaScript引擎是浏览器的组成部分之一。因为浏览器还要做很多别的事情,比如解析页面、渲染页面、Cookie管理、历史记录 等等。那么,既然是组成部分,因此一般情况下JavaScript引擎都是浏览器开发商自行开发的。比如:IE9的Chakra、Firefox的 TraceMonkey、Chrome的V8等等。
从而也看出,不同浏览器都采用了不同的JavaScript引擎。
浏览器的单线程及事件循环、宏任务和微任务 可阅读我前面的
JS事件循环、宏任务和微任务
浏览器详细的原理可查看
浏览器原理