JavaScript忍者秘籍(第2版)读书笔记一

396 阅读5分钟

第一章 无处不在的JavaScript

1.1 理解JavaScript

与java等语言相比,JavaScript函数式语言血统更多一些。JavaScript中的一些概念从根本上不同于其他的语言。

根本性的差异包括以下内容:

  1. 函数是一等公民——在JavaScript中,函数与其他对象共存,并且能够像任何其他对象一样地使用。函数可以通过字面量创建,可以赋值给变量,可以作为函数参数进行传递,甚至可以作为返回值从函数中返回。
  2. 函数闭包
  3. 作用域
  4. 基于原型的面向对象。不同于其他主流的面向对象语言(例如C#、Java、Ruby)使用基于类的面向对象,JavaScript使用基于原型的面向对象

第二章 运行时页面的构建

2.1 Web应用生命周期概览

典型客户端Web应用的生命周期从用户在浏览器地址栏输入一串URL,或单击一个链接开始。之后有两个步骤:

  1. 页面构建 —— 创建用户界面
  2. 事件处理 ——进入循环(序号5)从而等待事件(序号6)的发生,发生后调用事件处理器

应用的生命周期随着用户关掉或离开页面(序号7)而结束。

2.2 页面构建阶段

页面构建阶段目标是建立Web应用的UI,主要有以下两个步骤:

  1. 解析HTML并构建文档对象模型(DOM)
  2. 执行JavaScript代码

步骤1在浏览器处理HTML节点的过程中执行,步骤2会在HTML解析到一种特殊节点——脚本节点(包含或引用JavaScript代码的节点)时执行。页面构建阶段中,这两个步骤会交替执行多次

2.2.1 HTML解析和DOM构建

浏览器接受HTML代码时,页面构建阶段就开始了。如下图所示,在这种对HTML结构化表示的形式中,每个HTML元素都被当作一个节点。直到遇到第一个脚本元素,示例页面都在构建DOM。每当解析到脚本元素时,浏览器就会停止从HTML构建DOM,并开始执行JavaScript代码。

2.2.2 执行JavaScript代码

所有包含在脚本元素中的JavaScript代码由浏览器的JavaScript引擎执行。由于代码的主要目的是提供动态页面,故而浏览器通过全局对象提供了一个API使JavaScript引擎可以与之交互并改变页面内容。

浏览器暴露给JavaScript引擎的主要全局对象是window对象,它代表了包含着一个页面的窗口。window对象是获取所有其他全局对象、全局变量(甚至包含用户定义对象)和浏览器API的访问途径。全局window对象最重要的属性是document,它代表了当前页面的DOM。通过使用这个对象,JavaScript代码就能在任何程度上改变DOM,包括修改或移除现存的节点,以及创建和插入新的节点。

2.2.3 在页面构建阶段执行JavaScript代码

当浏览器在页面构建阶段遇到了脚本节点,它会停止HTML到DOM的构建,转而开始执行JavaScript代码。

一般来说,JavaScript代码能够在任何程度上修改DOM结构。但它不能对还没有创建的节点进行操作。所以我们一般把script元素放在页面底部的原因。如此一来,我们就不必担心是否某个HTML元素已经加载为DOM。

一旦JavaScript引擎执行到了脚本元素中JavaScript代码的最后一行,浏览器就退出了JavaScript执行模式,并继将余下的HTML构建为DOM节点。在这期间,如果浏览器再次遇到脚本元素,那么从HTML到DOM的构建再次暂停,JavaScript运行环境开始执行余下的JavaScript代码只要还有没处理完的HTML元素和没执行完的JavaScript代码,下面两个步骤都会一直交替执行。

  1. 将HTML构建为DOM。
  2. 执行JavaScript代码。

最后,当浏览器处理完所有HTML元素后,页面构建阶段就结束了。随后浏览器就会进入应用生命周期的第二部分:事件处理。

2.3 事件处理

客户端Web应用会对不同类型的事件作响应,如鼠标移动、单击和键盘按压等。因此,在页面构建阶段执行的JavaScript代码,除了会影响全局应用状态和修改DOM外,还会注册事件监听器(或处理器)。这类监听器会在事件发生时,由浏览器调用执行。有了这些事件处理器,应用也就有了交互能力。

2.3.1 事件处理器概览

浏览器执行环境的核心思想基于:同一时刻只能执行一个代码片段,即所谓的单线程执行模型。

当一个事件抵达后,浏览器需要执行相应的事件处理函数。这里不保证用户总会极富耐心地等待很长时间,直到下一个事件触发。所以,浏览器需要一种方式来跟踪已经发生但尚未处理的事件。为实现这个目标,浏览器使用了事件队列。

所有已生成的事件(无论是用户生成的,例如鼠标移动或键盘按压,还是服务器生成的,例如Ajax事件)都会放在同一个事件队列中,以它们被浏览器检测到的顺序排列。如下图中部所示,事件处理的过程可以描述为一个简单的流程图。

事件处理的过程可以描述为一个简单的流程图。

  • 浏览器检查事件队列头
  • 如果浏览器没有在队列中检测到事件,则继续检查
  • 如果浏览器在队列头中检测到了事件,则取出该事件并执行相应的事件处理器(如果存在)。在这个过程中,余下的事件在事件队列中耐心等待,直到轮到它们被处理。