浏览器原理:解释运行JavaScript相关

652 阅读7分钟

浏览器内核(渲染引擎)

浏览器想要在各设备上运行涉及到对操作系统的适配

IEFirefoxchromeSafari
windows是(5.1.7之前)
Mac OS
Linux
Android
iOS

window、chrome最适配

浏览器内核:浏览器内核主要指的是浏览器的渲染引擎

  • Trident:IE
  • Gecko:Firefox
  • WebKit:safari 、chrome 、 android、 webOS
  • blink:chrome 在浏览器地址栏输入chrome://version,回车可以查看浏览器信息

现代的主流浏览器大都采用的双核,开发者可以通过meta设置告诉浏览器切换内核渲染

<meta name='renderer' content='webkit'>

在这里插入图片描述

浏览器与JavaScript

今天的web对JavaScript程序员而言已经是一个完善的应用开发平台。 浏览器专注于格式化文本和图片的显示,同时与原生OS一样,浏览器也提供了其他服务-图形、视频、音频、网络、存储、线程的web API。

node有自己的唯一实现和官方文档,web API则是通过主要浏览器厂商的共识来确定。设计有缺陷的API会短暂出现document.write将文本字符串写入一个由 打开的文档流 innerHTML

每个浏览器窗口或者标签页都有一个全局对象,全局对象

  • 定义了JavaScript语言内置类型和函数

  • 代表当前浏览器窗口定义了history、innerWidth等web API的属性

  • 包含各种web API的入口,fetch发起网络请求、Audio播放声音

  • 常见的触发硬件加速的css属性:transform、opacity、filters、Will-change

  • window.requestAnimationFrame() 该方法传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

var function 声明是通过所在全局对象的属性共享的,而const let class会被共享且拥有相同的文档作用域,但是不作为JavaScript可以访问到的任何对象的属性存在。

客户端JavaScript时间线

我们可以把JavaScript程序的执行想象成发生在两个阶段:顺序执行+异步、事件驱动

浏览器两大核心:渲染引擎+JavaScript引擎

  1. 浏览器创建document对象开始解析网页,将HTML解析成DOM,CSS解析成CSSOM document.readyState === loading
  2. 遇到非异步的script元素时候把网页渲染的权力转交给JavaScript引擎,处理完毕后再恢复到渲染引擎上
  3. 遇到async、defer的script元素,开始下载文档并继续解析
  4. 文档解析完成:document.readyState === interactive
  5. 顺序执行defer的script元素(可以访问完整文档元素)
  6. 浏览器在document上派发DOMContentLoaded:进入等待异步阶段
  7. 文档已经解析完全,但是浏览器可能在等所有外部资源都加载完成,且所有async的script元素执行完成后,进入document.readyState === complete,浏览器在window上派发load事件
  8. 进入事件驱动阶段:用户输入事件、定时器超时...

注意解析!==渲染

  • type=module的JavaScript文件默认是defer
  • 浏览器中的图片是异步加载的
  • beforeunload事件:DOM树构建完成后立即触发DOMContentLoaded事件,不用等图片、JavaScript文件、CSS文件或其他资源文件。其他外部资源加载成功之后,触发window的load事件。
  • 不支持DOMContentLoaded事件的,用超时为0的setTimeout()函数来设置处理程序。

script 元素

在浏览器不支持脚本或者支持被关闭就会渲染noscript元素中的内容。

  1. 行内JavaScript代码
  2. 动态加载脚本 (不提倡,预资源加载器不可见)
  3. 外部JavaScript文件(后文主要围绕后者会遇到的加载和执行问题展开)
  • src指向外部执行文件,使用该属性后,浏览器会同步下载(get请求)并执行脚本文件,忽略元素间代码。同步会影响性能,所以推出了defer、async
  • defer(外部文件专有)异步下载推迟对脚本的解释(页面剩余部分完成后执行)。更好的处理方式时选择把推后执行的脚本放在文档后面
  • async(外部文件专有)异步下载完成后解释,实际结果乱序(相对于页面剩余部分被异步执行),异步脚本不应在加载期间修改DOM。注意有的浏览器不支持
  • type 使用MIME类型字符串 默认text/javascript 注意:module
  • charset
  • crossorigin 与CORS设置相关。anonymous配置文件请求不必设置凭据标志;use-credentials设置凭据。所有能引入跨域资源的标签包括 link 和 img 之类,都有
  • integrity 允许对比接收到的资源和指定的加密签名以验证子资源的完整性。用于确保CDN不会提供恶意内容。

按需加载脚本

function importScript(url) {
    return new Promise((resolve, reject) => {
        let s = document.createElement('script');
        s.onload = () => resolve();
        s.onerror = (e) => reject(e);
        s.src = url;
        document.head.append(s);
    });
}

script元素的作用: 在网页中嵌入数据,iconfont的机制原理就是注入script元素,得到文件后执行生成svg图标

外部css

  • CSS不会阻塞 DOM 的解析,但是DOM渲染的阻塞情况看具体的浏览器

  • CSS之后的DOM元素渲染:CSS标签写在body标签中,CSS后面的body内容会和他一同预加载,CSS加载完成再渲染后面的body。

  • CSS之前的DOM元素渲染:各个浏览器处理的策略不太相同,谷歌(主流做法)选择CSS

  • 阻塞页面渲染,在所有css下载完成后再进行渲染(白屏等待)。而IE的选择是先选择展示前面的内容(载入速度比较快)

  • 综上CSS一般写在head中。

  • 浏览器绘制顺序:先绘制非定位元素再绘制定位

  • z-index只对定位元素起作用;会创建一个层叠上下文

异步控制台

  • console.方法族没有规范,并不是JavaScript正式的部分,而是由宿主环境添加到JavaScript中的,不同的浏览器和JavaScript环境按照自己的设计实现。
  • 考虑到在很多程序中I/O是非常低速的阻塞部分,有些环境选择在后台异步处理控制台I/O能提高性能,比如
const a = {
    index:1,
};
console.log(a);// 输出不一定是1
a.index++;

所以推荐:

  • 断点调试
  • JSON.stringify

浏览器进程

  • Browser进程:浏览器的主线程,负责浏览器界面的显示、各个页面的管理,创建销毁其他类型进程
  • Renderer进程:一个网页的渲染进程,每个网页都是独立的进程,可能有多个,沙箱模型启动之后也会有改变
  • GPU进程:最多只有一个,当仅当GPU硬件加速打开的时候才会被创建,主要用于对3D图形加速调用的实现
  • NPAPI插件进程
  • Pepper插件进程 在这里插入图片描述

浏览器运行状态的信息文件

在这里插入图片描述

window.open

Window 接口的 open() 方法,是用指定的名称指定的资源加载到浏览器上下文(窗口 window ,内嵌框架 iframe 、标签 tab )

let windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]);

let windowObjectReference;
let strWindowFeatures = `
    menubar=yes,
    location=yes,
    resizable=yes,
    scrollbars=yes,
    status=yes
`;

function openRequestedPopup() {
    windowObjectReference =
    window.open(
        "http://www.cnn.com/",
        "CNN_WindowName",
        strWindowFeatures
    );
}
  • 如果定义了 strWindowFeatures 参数,那么没有在这个字符串中列出的特性会被禁用或移除 (除了 titlebar 和 close 默认设置为yes)
  • 如果已经存在以 strWindowName 为名称的窗口,则不再打开一个新窗口,而是把 strUrl 加载到这个窗口中,并忽略参数 strWindowFeatures 。
  • 如果没有指定url,带有默认工具栏的空白窗口(加载about:blank)
  • strUrl设为空字符串时,可以在不改变窗口地址的情况下获得一个已经打开的同名窗口的引用。如果要在每次调用 window.open()时都打开一个新窗口,则要把参数 strWindowName 设置为 _blank。
  • 调用失败,返回 null
  • 成功,打开的新窗口对象的引用。如果父子窗口满足“同源策略”,可以通过这个引用访问新窗口的属性或方法。