多进程
单进程缺点:
- 不稳定:一个崩了整个浏览器都崩了
- 不流畅:有耗时的任务其他的也也慢,而且有内存泄漏的话,会更慢
- 不安全:一些不安全的插件可能会有病毒等
目前多进程模型:
- 浏览器进程主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
- 渲染进程核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
- GPU 进程其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。
- 网络进程主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
- 插件进程主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
HTML、CSS和JavaScript,是如何变成页面的?
递归栈溢出
解决方案:
- 尾递归优化(尾调用)
- 蹦床函数(trampoline)可以将递归执行转为循环执行(这里有一个库的实现 underscore.js/template)它将递归转化为 while 循环去绕过 JavaScript 的限制还可以看看这个
// 一个蹦床函数,只要传入的递归函数返回值还是个函数,就手动调用
function trampoline(f) {
return function trampolined(...args) {
let result = f.bind(null, ...args);
while (typeof result === 'function') result = result();
return result;
};
}
// 测试
const recursiveFn = trampoline(function _recursiveFn(n) {
if (n < 0) return; // 何时停止递归写在这
return () => _recursiveFn(n - 1); // 如果继续递归,记得返回个函数
});
recursiveFn(100000);
console.log('No range error!');
冷知识集合
- beforeunload 事件允许页面在退出之前执行一些数据清理操作,还可以询问用户是否要离开当前页面,比如当前页面可能有未提交完成的表单等情况,因此用户可以通过 beforeunload 事件来取消导航,让浏览器不再执行任何后续工作。
- Chrome 默认采用每个标签对应一个渲染进程,但是如果两个页面属于同一站点,那这两个标签会使用同一个渲染进程。
- Content-Type 是 HTTP 头中一个非常重要的字段, 它告诉浏览器服务器返回的响应体数据是什么类型,然后浏览器会根据 Content-Type 的值来决定如何显示响应体的内容。