从建立 http 连接开始,到页面展示在浏览器中,一共经过了加载,执行,渲染,重构等几个阶段。
加载
比如:百万级的 PV,并发量过大怎么办 ?
-
PV(访问量):即 Page View,页面刷新一次算一次。也叫并发量。
-
UV(独立访客):即 Unique Visitor,一个客户端(电脑,手机)为一个访客
由此,我们可以基于并发量和单线程来做。
资源加载优化两个方向:
-
开源
增加域名,简单来说就是 cdn。
-
节流
资源压缩gzip,减少请求数精灵图片,不需要立即使用的文件延迟加载,未来要执行的预加载等。
阻塞性优化
js 页面加载之后是否要立即执行?立即执行是否会影响页面渲染?
过去浏览器在加载和执行 js 文件时是阻塞状态,就是按照栈原理一个一个来;所以,原来要求把 js 文件放到 html 代码底部前。
现代浏览器某种程度上解决了并行加载的问题,也可以进行预加载,但是执行之后会否对页面造成重排?
- 灵活应用 defer、async 、动态创建script标签。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
</head>
<body>
<!-- html code -->
<script type="text/javascript" src="//js.cdn.com/currentPage-part1.js" defer></script>
<script type="text/javascript" src="//js.cdn.com/currentPage-part2.js" async></script>
</body>
</html>
执行
简化终止条件
for (var i = 0; i < values.length; i++) {
process(values[i]);
}
for (var i = 0, len = values.length; i < len; i++) {
process(values[i]);
}
避免字符串执行语句
eval("console.log('hello world');"); // 避免
var sayHi = new Function("console.log('hello world');"); // 避免
setTimeout("console.log('hello world');", 100); // 避免
/**
* 以上代码是包含在字符串中的,即在JS代码运行的同时必须新启运一个解析器来解析新的代码。
* 实例化一个新的解析器有不容忽视的开销,故这种代码要比直接解析要慢。
* 正确的应该这么做:
*/
console.log("hello world");
var sayHi = function() {
console.log("hello world");
};
setTimeout(function() {
console.log("hello world");
}, 100);
最小化语句数
- 多个变量声明
// 避免
var i = 1;
var j = "hello";
var arr = [1, 2, 3];
var now = new Date();
// 提倡
var i = 1,
j = "hello",
arr = [1, 2, 3],
now = new Date();
- 插入迭代值
// 避免
var name = values[i];
i++;
// 提倡
var name = values[i++];
- 尽量使用数组和对象字面量,避免使用构造函数 Array(),Object()
// 避免
var a = new Array();
a[0] = 1;
a[1] = "hello";
a[2] = 45;
var o = new Obejct();
o.name = "bill";
o.age = 13;
// 提倡
var a = [1, "hello", 45];
var o = {
name: "bill",
age: 13
};
算法和流程控制优化
-
switch 代替 if-else
-
三目运算
-
判断可能性从大到小
-
将字符串、变量、方法存到数组或对象中
function getweek() {
var w = ["日", "一", "二", "三", "四", "五", "六"],
now = new Date(),
d = now.getDay();
return "星期" + w[d];
}
重排 reflow 和重绘 repaint
重排:由于布局的改变引起的页面重新渲染
重绘:由于样式的改变引起的页面重新渲染
如何触发
- 添加或删除元素
- 元素的位置发生改变
- 元素的尺寸发生改变
- 元素的宽高发生改变
- 浏览器窗口尺寸改变
如何避免
- 尽可能少的访问某些变量 offsetTop、scrollHeight、clientWidth等
- 一次性的创建元素之后再添加到页面上
- 使用visibility代替display
总的来说:少访问 DOM,在 js 里处理计算完了再一次性修改。使用成熟的框架
利用闭包缓存数据
某个方法内部可以存储计算过的数据或变量:
function memfacttail(n) {
if (!memfacttail.cache) {
memfacttail.cache = {
"0": 1,
"1": 1
};
}
if (!memfacttail.cache.hasOwnProperty(n)) {
memfacttail.cache.n = n * memfacttail(n - 1);
}
return memfacttail.cache.n;
}
console.log(memfacttail(4)); // 4*3*2*1 = 24;