2020-05-14:第八章,BOM对象
ECMAScript相关的内容已经结束,很明显,ECMAScript构成了JavaScript的核心,但是如果要在Web中使用Js,那么BOM(浏览器对象模型)才是事实上的核心。BOM是js中对象的一种,他提供了很多与浏览器进行交互的功能。这些功能与确切的任何一个网页都无关,他们只是与浏览器交互的入口。BOM提供的是与浏览器交互的可能性。
Po两个参考链接,我的笔记也基本来源于这两个链接。摘抄了一些重点部分,省略了一些具体的实现。
https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/
https://blog.csdn.net/qq_44721831/article/details/102575229
在这里简单啰嗦几句有关浏览器与js的关系:简而言之。浏览器一个大剧院,js则是一场演出的剧本。浏览器中包含了可以识别js的js解析引擎(剧院中有看得懂剧本的演员),解析引擎根据js的内容表达信息(演员根据剧本演出)。不同浏览器的解析引擎都不同。像IE9使用微软自家的ChaKra,Firefox使用TraceMonkey,而Chrome使用大名鼎鼎的V8。
一个浏览器有许多个部分组成:
浏览器构成用户界面(User Interface) - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
浏览器引擎(Browser engine) - 在用户界面和呈现引擎之间传送指令。
呈现引擎(Rendering engine) - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
网络(Networking) - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
用户界面后端(UI Backend) - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
JavaScript 解释器(JavaScript Interpreter) - 用于解析和执行 JavaScript 代码。
数据存储(Data Persistence) - 这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。
作为前端开发者,我们最经常打交道的就是呈现引擎和js解释器的部分。因此我们也只着眼于这两部分。
呈现引擎
又称渲染引擎,也是我们最常提的所谓"浏览器内核"。从线程角度理解可以称为UI线程。浏览器内核由不同厂家按照W3C标准自行研发。常见的内核有四种:Trident(IE内核)、Gecko(Firefox)、Blink(Safari内核,也是chrome的内核原型)、Webkit(chrome28及往后版本)。
Trident: 俗称 IE 内核,也被叫做 MSHTML 引擎,目前在使用的浏览器有 IE11 -,以及各种国产多核浏览器中的 IE 兼容模块。另外微软的 Edge 浏览器不再使用 MSHTML 引擎,而是使用类全新的引擎 EdgeHTML。
Gecko: 俗称 Firefox 内核,Netscape6 开始采用的内核,后来的 Mozilla FireFox(火狐浏览器)也采用了该内核, Gecko 的特点是代码完全公开,因此,其可开发程度很高,全世界的程序员都可以为其编写代码,增加功能。因为这是个开源内核,因此受到许多人的青睐,Gecko 内核的浏览器也很多,这也是 Gecko 内核虽然年轻但市场占有率能够迅速提高的重要原因。
Presto: Presto 是挪威产浏览器 opera 的 “前任” 内核,最新的 opera 浏览器内核现为 Blink。
Webkit: Safari 内核,也是 Chrome 内核原型,主要是 Safari 浏览器在使用的内核,也是特性上表现较好的浏览器内核。也被大量使用在移动端浏览器上。
Blink: 由 Google 和 Opera Software 开发,在Chrome(28及往后版本)、Opera(15及往后版本)和Yandex浏览器中使用。Blink 其实是 Webkit 的一个分支,添加了一些优化的新特性,例如跨进程的 iframe,将 DOM 移入 JavaScript 中来提高 JavaScript 对 DOM 的访问速度等,目前较多的移动端应用内嵌的浏览器内核也渐渐开始采用 Blink。
呈现引擎,顾名思义,最重要的作用就是在浏览器上显示请求内容。他开始会从网络层获取请求文档的内容(HTML),随后开始解析HTML文档,将各个标签顺序转化成DOM树上的DOM节点。同时也会解析外部CSS文件以及样式元素中的样式数据。将DOM树与样式元素结合后,呈现引擎创建了另外一颗树结构:呈现树。
呈现树被构建完毕后,进入布局阶段,引擎为每个节点分配一个确切的坐标。接着进入绘制阶段,呈现引擎通过操作UI Backend层绘制节点内容。
总结一下就是:读取文档 - 构建DOM树 - 构建呈现树 - 进行布局 - 进行绘制。HTML文档的读取和构建树结构以及设置布局之间是互相异步的。
8.1 window 对象
BOM的核心对象是window,它是一个浏览器的实例。在浏览器中,window对象既是开发人员通过js访问浏览器窗口的根接口,又是ECMAScript中定义的global对象。所以当我们在浏览器中定义任何一个对象,变量或函数时,window都是他们的global对象。
8.1.1全局作用域
在浏览器的全局作用域中声明的变量,函数会成为window对象的属性和方法。当你在一个html文档或在Network中获取到的html文档,或是浏览器的F12-console控制台中定义全局变量和全局函数时,其都归属于window对象。这时this.XX 映射到window.XX。因此,在某种意义上来说,直接定义全局变量和定义window.property几乎是一样的。唯一的区别是在window上定义属性,可以通过delete操作符删除。但是全局变量是无法通过delete删除。
另外需要注意的是,尝试访问未声明的变量会抛错,但是通过查询window对象,可以知道某个可能未声明的变量的具体情况:
例如这样8.1.2窗口关系以及框架
如果一个页面包含框架元素(frame),则多个frame都会拥有自己的window对象,他们顺序保存再最外层页面的window.frames集合里,可以通过下标访问,也可以通过给frame元素定义name属性来进行访问。
在html中定义了一个框架,分别通过下标0和name属性frame1访问除了通过最高层的框架的window.frames访问下层框架的window属性,还可以通过top.frames[]来访问下层框架的window属性。这样做的好处是避免在框架嵌套时产生误解,因为在任何一个框架中编写代码时,window都只指向当前的框架实例,这里框架有点像this,我们知道this的定义是,this永远指向当前执行环境的环境对象。而window则是永远指向当前的框架实例。也因此我们更推荐使用top来逐层访问下层框架的window对象。
在只有两层关系时,winodw,top,frames访问到的都是我们定义的一层框架的window对象与top相对的还有另外一个window对象是parent。parent对象永远指向当前框架的直接上层框架,如果parent对象没有上层对象(属于浏览器窗口,那么他就与top相同,都指向浏览器窗口)。
与框架有关的还有另外一个对象,是self,self永远指向当前框架内的window对象,因此其实window和self可以随时互换使用。