1.Webkit(Safari 内核)
浏览器内核可以分为四种:Trident(IE)、Gecko(火狐)、Blink(Chrome、Opera)、Webkit(Safari)
webkit的架构图
- 最底层是操作系统,WebKit 可以在不同的操作系统上工作
- 操作系统之上的就是 WebKit 依赖的第三方库,这些库是 WebKit 运行的基础
- 再往上一层就是 WebKit 项目了,图中又将其分为两层 WebCore JavaScriptCore WebKit Ports
WebCore
和WebKit Ports
之上的层主要提供嵌入式编程接口,提供给浏览器调用。接口层的定义也与移植密切相关,而不是 WebKit 有一个统一接口。WebKit2 嵌入式接口不是 WebKit 嵌入式接口的简单修改,而是为了浏览环境的安全性和稳定性原因考虑而引入了跨进程的架构。
其中,WebCore是Webkit的核心部分,它实现了对文档的模型化,包括了CSS, DOM, Render等的实现, JavaSript Core显然是对JavaSript支持的实现。WebKitPort方面的内容是可以很广的,例如可将不同的图形库、网络库与WebCore集成,提供不同的Port接口供外部程序使用等,例如同样在windows平台上可以运行的Google Chrome和Safari就是针对WebKit的不同移植。
2.内存泄漏处理
- 程序的运行需要内存。只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存。
- 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。
- 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
常见的内存泄露及解决方法
2.1 意外的全局变量:
由于 js 对未声明变量的处理方式是在全局对象上创建该变量的引用。如果在浏览器中,全局对象就是 window 对象。变量在窗口关闭或重新刷新页面之前都不会被释放,如果未声明的变量缓存大量的数据,就会导致内存泄露。
未声明变量
function fn() {
a = 'global variable'
}
fn()
使用 this 创建的变量(this 的指向是 window)。
function fn() {
this.a = 'global variable'
}
fn()
解决方法:
避免创建全局变量
使用严格模式,在 JavaScript 文件头部或者函数的顶部加上 use strict
。
2.2 闭包引起的内存泄漏:
原因:闭包可以读取函数内部的变量,然后让这些变量始终保存在内存中。如果在使用结束后没有将局部变量清除,就可能导致内存泄露。
function fn () {
var a = "I'm a";
return function () {
console.log(a);
};
}
解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中。
比如:在循环中的函数表达式,能复用最好放到循环外面。
// bad
for (var k = 0; k < 10; k++) {
var t = function (a) {
// 创建了10次 函数对象。
console.log(a)
}
t(k)
}
// good
function t(a) {
console.log(a)
}
for (var k = 0; k < 10; k++) {
t(k)
}
t = null
2.3 没有清理的 DOM 元素引用
原因:虽然别的地方删除了,但是对象中还存在对 dom 的引用。
// 在对象中引用DOM
var elements = {
btn: document.getElementById('btn'),
}
function doSomeThing() {
elements.btn.click()
}
function removeBtn() {
// 将body中的btn移除, 也就是移除 DOM树中的btn
document.body.removeChild(document.getElementById('button'))
// 但是此时全局变量elements还是保留了对btn的引用, btn还是存在于内存中,不能被GC回收
}
解决方法:手动删除,elements.btn = null
。
2.4 被遗忘的定时器或者回调
定时器中有 dom 的引用,即使 dom 删除了,但是定时器还在,所以内存中还是有这个 dom。
// 定时器
var serverData = loadData()
setInterval(function () {
var renderer = document.getElementById('renderer')
if (renderer) {
renderer.innerHTML = JSON.stringify(serverData)
}
}, 5000)
// 观察者模式
var btn = document.getElementById('btn')
function onClick(element) {
element.innerHTMl = "I'm innerHTML"
}
btn.addEventListener('click', onClick)
解决方法:手动删除定时器和 dom。
removeEventListener 移除事件监听
3. 页面加载和渲染
3.1 如何加载&#