1、浏览器的核心是两部分:渲染引擎和 JavaScript 解释器(又称 JavaScript 引擎)。

     渲染引擎的主要作用是,将网页代码渲染为用户视觉可以感知的平面文档。

     不同的浏览器有不同的渲染引擎。

     渲染引擎处理网页,通常分成四个阶段。

  1. 解析代码:HTML 代码解析为 DOM,CSS 代码解析为 CSSOM(CSS Object Model)。
  2. 对象合成:将 DOM 和 CSSOM 合成一棵渲染树(render tree)。
  3. 布局:计算出渲染树的布局(layout)。
  4. 绘制:将渲染树绘制到屏幕。

     以上四步并非严格按顺序执行,往往第一步还没完成,第二步和第三步就已经开始了。所以,会看到这种情况:网页的 HTML 代码还没下载完,但浏览器已经显示出内容了。

 

2. 渲染引擎,优化重绘重流的小技能:

  • 读取 DOM 或者写入 DOM,尽量写在一起,不要混杂。不要读取一个 DOM 节点,然后立刻写入,接着再读取一个 DOM 节点。
  • 缓存 DOM 信息。
  • 不要一项一项地改变样式,而是使用 CSS class 一次性改变样式。
  • 使用documentFragment操作 DOM
  • 动画使用absolute定位或fixed定位,这样可以减少对其他元素的影响。
  • 只在必要时才显示隐藏元素。
  • 使用window.requestAnimationFrame(),因为它可以把代码推迟到下一次重流时执行,而不是立即要求页面重流。
  • 使用虚拟 DOM(virtual DOM)库。

 

3.  浏览器的JavaScript 引擎

     主要功能:读取网页中的JavaScript代码,对其处理后运行。

     JavaScript 是一种解释型语言,即,它不需要编译,由解释器实时运行。好处:运行和修改都比较方便,刷新页面就可以重新解释;缺点:每次运行都要调用解释器,系统开销较大,运行速度慢于编译型语言。

字节码(bytecode)的中间代码,以提高运行速度。

早期,浏览器内部对 JavaScript 的处理过程如下:

  1. 读取代码,进行词法分析(Lexical analysis),将代码分解成词元(token)。
  2. 对词元进行语法分析(parsing),将代码整理成“语法树”(syntax tree)。
  3. 使用“翻译器”(translator),将代码转为字节码(bytecode)。
  4. 使用“字节码解释器”(bytecode interpreter),将字节码转为机器码。

JIT),即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编译结果缓存(inline cache)。通常,一个程序被经常用到的,只是其中一小部分代码,有了缓存的编译结果,整个程序的运行速度就会显著提升。

    字节码不能直接运行,而是运行在一个虚拟机(Virtual Machine)之上,一般也把虚拟机称为 JavaScript 引擎。

    并非所有的 JavaScript 虚拟机运行时都有字节码,有的 JavaScript 虚拟机基于源码,即只要有可能,就通过 JIT(just in time)编译器直接把源码编译成机器码运行,省略字节码步骤。这一点与其他采用虚拟机(比如 Java)的语言不尽相同。这样做的目的,是为了尽可能地优化代码、提高性能。下面是目前最常见的一些 JavaScript 虚拟机:

 

4.  window对象 指当前浏览器窗口,也是当前页面的顶层对象,即最高一层的对象。

     一个变量如果未声明,那么默认就是顶层对象的属性。

    window.open 可以打开新窗口。

 

5. window.requestAnimationFrame() 推迟某个函数 到浏览器下一次重流时执行,执行完了才会进行下一次重绘。

    如果某个函数会改变网页的布局,一般就放在window.requestAnimationFrame()里面执行,这样节能,网页效果平滑。

    window.requestIdleCallback()  推迟到系统资源空闲时执行。

 

6.window.navigator属性指向一个包含浏览器和系统信息的 Navigator 对象。脚本通过这个属性了解用户的环境信息。

 

7.Cookie 是服务器保存在浏览器的一小段文本信息,一般大小不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息。

Cookie 主要保存状态信息,以下是一些主要用途。

  • 对话(session)管理:保存登录、购物车等需要记录的信息。
  • 个性化信息:保存用户的偏好,比如网页的字体大小、背景色等等。
  • 追踪用户:记录和分析用户行为。

Cookie 不是一种理想的客户端储存机制。它的容量很小(4KB),缺乏数据操作接口,而且会影响性能。客户端储存应该使用 Web storage API 和 IndexedDB。只有那些每次请求都需要让服务器知道的信息,才应该放在 Cookie 里面。

每个 Cookie 都有以下几方面的元数据。

  • Cookie 的名字
  • Cookie 的值(真正的数据写在这里面)
  • 到期时间(超过这个时间会失效)
  • 所属域名(默认为当前域名)
  • 生效的路径(默认为当前网址)

 

8. AJAX (Asynchronous JavaScript and XML ) :AJAX 通过原生的XMLHttpRequest对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理。现在,服务器返回的都是 JSON 格式的数据,XML 格式已经过时了,但是 AJAX 这个名字已经成了一个通用名词,字面含义已经消失了。

AJAX 包括以下几个步骤。

  1. 创建 XMLHttpRequest 实例
  2. 发出 HTTP 请求
  3. 接收服务器传回的数据
  4. 更新网页数据

 

9.同源:三个相同;协议相同,域名相同,端口相同。

     A 网页设置的 Cookie,B 网页不能打开,除非这两个网页“同源”。同源,是为了保证用户信息的安全,防止恶意的网站窃取数据。

    如果非同源,有3种限制:

     (1) 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。

     (2) 无法接触非同源网页的 DOM。

     (3) 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。

 

9. CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨域的服务器,发出XMLHttpRequest请求,从而克服了 AJAX 只能同源使用的限制

 

10. Storage 接口用于脚本在浏览器保存数据。两个对象部署了这个接口:window.sessionStoragewindow.localStorage

  • sessionStorage :保存的数据用于浏览器的一次会话(session),当会话结束(通常是窗口关闭),数据被清空;
  • localStorage: 保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前的数据。

   2种stroage,除了保存期限不同,其他方面一致,都是key-value的格式。

    storage 支持数据变化的事件监听。

 

11. window.history属性指向 History 对象,它表示当前窗口的浏览历史。

    History 对象保存了当前窗口访问过的所有页面网址。

    window.history.length  //代表当前窗口访问过几个网址

    history.back()   or history.go(-1)    //回退到上一个页面

    History.state :  History 堆栈最上层的状态值。

    History.forward() : 移动到下一个网址,相当于浏览器的前进按钮,对于最后一个访问的网址,该方法无效果。

     History.go():接受一个整数作为参数,以当前网址为基准,移动到参数指定的网址,比如go(1)相当于forward()go(-1)相当于back()。如果参数超过实际存在的网址范围,该方法无效果;如果不指定参数,默认参数为0,相当于刷新当前页面

    注意,移动到以前访问过的页面时,页面通常是从浏览器缓存之中加载,而不是重新要求服务器发送新的网页。

 

12. Location对象是浏览器提供的原生对象,提供 URL 相关的信息和操作方法。通过window.locationdocument.location属性,可以拿到这个对象。

Location对象提供以下属性。

  • Location.href:整个 URL。
  • Location.protocol:当前 URL 的协议,包括冒号(:)。
  • Location.host:主机。如果端口不是协议默认的80433,则还会包括冒号(:)和端口。
  • Location.hostname:主机名,不包括端口。
  • Location.port:端口号。
  • Location.pathname:URL 的路径部分,从根路径/开始。
  • Location.search:查询字符串部分,从问号?开始。
  • Location.hash:片段字符串部分,从#开始。
  • Location.username:域名前面的用户名。
  • Location.password:域名前面的密码。
  • Location.origin:URL 的协议、主机名和端口。

 

13. Location.href 写入新的URL地址,浏览器会立刻跳转到这个新地址。

// 跳转到新网址
document.location.href = 'http://www.example.com';

这个特性常常用于让网页自动滚动到新的锚点。

document.location.href = '#top';
// 等同于
document.location.hash = '#top';

直接改写location,相当于写入href属性。

document.location = 'http://www.example.com';
// 等同于
document.location.href = 'http://www.example.com';

另外,Location.href属性是浏览器唯一允许跨域写入的属性,即非同源的窗口可以改写另一个窗口(比如子窗口与父窗口)的Location.href属性,导致后者的网址跳转。Location的其他属性都不允许跨域写入。

其他方法:

Location.assign() : 跳转到新的URL

Location.replace(): 跳转到新的URL, 同时替换History中当前网址

Location.reload(): 刷新

 

14: URL的编码 和解码

  1)网页的URL只能包含合法的字符。合法字符包含2类:

  • URL 元字符
  • 分号(;),逗号(,),斜杠(/),问号(?),冒号(:),at(@),&,等号(=),加号(+),美元符号($),井号(#
  • 语义字符
  • a-zA-Z0-9,连词号(-),下划线(_),点(.),感叹号(!),波浪线(~),星号(*),单引号('),圆括号(()

       除了以上字符,其他字符出现在URL之中都必须转义, 规则是根据操作系统的默认编码,将每个自己转为百分号(%)加上两个大写的十六进制字母。

   2)JavaScript 提供四个 URL 的编码/解码方法。

  • encodeURI()
  • 用于转码整个 URL。它的参数是一个字符串,代表整个 URL。它会将元字符和语义字符之外的字符,都进行转义。
  • encodeURIComponent()
  • 用于转码 URL 的组成部分,会转码除了语义字符之外的所有字符,即元字符也会被转码。所以,它不能用于转码整个 URL。它接受一个参数,就是 URL 的片段。
  • decodeURI()
  • decodeURIComponent()

 

15. URL 对象是浏览器的原生对象,可用来构造、解析和解码URL。一般情况下,通过window.URL可以拿到这个对象。

   <a>元素和<area>元素都部署了这个接口。这就是说,它们的 DOM 节点对象可以使用 URL 的实例属性和方法。

var a = document.createElement('a');
a.href = 'http://example.com/?foo=1';

a.hostname // "example.com"
a.search // "?foo=1"

上面代码中,a<a>元素的 DOM 节点对象。可以在这个对象上使用 URL 的实例属性,比如hostnamesearch。

 

16. Blob 对象表示一个二进制文件的数据内容,比如一个图片文件的内容就可以通过 Blob 对象读写。它通常用来读写文件,它的名字是 Binary Large Object (二进制大型对象)的缩写。它与 ArrayBuffer 的区别在于,它用于操作二进制文件,而 ArrayBuffer 用于操作内存。

 

17.File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种特殊的 Blob 对象,所有可以使用 Blob 对象的场合都可以使用它。

 

18.表单(<form>)用来收集用户提交的数据,发送到服务器。比如,用户提交用户名和密码,让服务器验证,就要通过表单。表单提供多种控件,让开发者使用,具体的控件种类和用法请参考 HTML 语言的教程

 

19. IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。

IndexedDB 具有以下特点。

(1)键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以“键值对”的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

(2)异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

(3)支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

(4)同源限制。 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

(5)储存空间大。 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。

(6)支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

 

20. Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。

       Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

Web Worker 有以下几个使用注意点。

(1)同源限制

分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

(2)DOM 限制

Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用documentwindowparent这些对象。但是,Worker 线程可以使用navigator对象和location对象。

(3)全局对象限制

Worker 的全局对象WorkerGlobalScope,不同于网页的全局对象Window,很多接口拿不到。比如,理论上 Worker 线程不能使用console.log,因为标准里面没有提到 Worker 的全局对象存在console接口,只定义了Navigator接口和Location接口。不过,浏览器实际上支持 Worker 线程使用console.log,保险的做法还是不使用这个方法。

(4)通信联系

Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

(5)脚本限制

Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

(6)文件限制

Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。