- 当浏览器遇到<script>标签时,在大多数情况下,它会停止渲染页面,直到完成对该脚本的读取和解析。所以,把所有能够移动的<script>标签挪至HTML的</body>标签之前。
- 将JavaScript文件编制成GZip编码传输。(详细资料见本书P85)。
- 缩编、混淆和编译:
- 缩编是将JavaScript代码中所有的空格个换行符进行移除,以产出更小体积的代码文件,但是处理后的代码仍保留着由开发者编写的完全相同的语句。
- 混淆是一种更高级的代码优化方法,它会着眼于变量和函数名称,并找出哪些是可全局性访问,哪些限定在特定的作用域之内。
- 编译时一种更先进的处理方法,它会全面地对代码进行分析,并对代码中的语句进行简化、缩减、整合,生成有着相同行为的另一语句。与缩编和混淆相结合是,这是产生最小体积文件的最有效的方法。
优化文档对象的操作:
- 以变量保存对DOM元素的引用以便后续使用
var header = document.getElementById("header"),
nav = document.getElementById("nav"); - 通过对单独父元素的引用来访问其子DOM元素,不要直接获取对整个页面的引用并使用它,因为所需的内存占用的是整个DOM树,再加上JavaScript要深入该树查找需要访问的元素所花费的时间,这对应用程序将产生负面的性能影响。
var wrapper = document.getElementById("wrapper"),
header = wrapper.getElementsByTagName("div")[0],
nav = wrapper.getElementsByTagName("div")[1]; - 对新建元素实施DOM修改操作后才将其添加至当前实时页面
var list = document.createElement("ul"),
listItem = document.createElement("li");
//先在JavaScript中尽可能地实施所有的DOM操作
listItem.innerHTML = "I am a list item";
list.appendChild(listItem);
//
document.body.appendChild(list); - 复制已经存在的元素以提高性能
var list1 = document.createElement("ul"),
list2;
list1.className = "list";
list2 = list1.cloneNode(true); - 应用css类至DOM元素以减少浏览器重排
var nav = document.getElementById("nav");
nav.style.backgroundColor = "#000";//在浏览器中引发一次重排
nav.style.color = "#fff";//引发一次重排
····
正确做法应为:
nav.className = "selected";
or
nav.style.display = "none";
nav.style.backgroundColor = "#000";
···
nav.style.display = "block"; - 事件委托至父元素——DOM事件会从其首次被触发的元素起开始冒泡,一直到文档结构的最顶端。
- 以变量保存对DOM元素的引用以便后续使用
// 获取对列表元素的引用,此列表包含我们想要为其指派事件处理函数的所有链接
var list = document.getElementById("list");
// 定义一个函数,当链接或链接中的某个元素被执行时(点击或回车),执行该函数
function onClick(evt){
// 利用事件的target属性来获取对所点击的实际元素的引用
var clickedElem = evt.target,
tagNameSought = "A";
//检查所点击的元素是否为我们所要的类型,在这里检查它是否为<a>标签
if(clickedElem && clickedElem.tagName === tagNameSought){
window.open(clickedElem.href);
}
}
5.提升函数性能(特别针对计算量大的函数)
// 函数memoize()需要传入一个函数作为参数,返回相同的函数但增加了存储功能
function memoize(fn){
return function(){
var propertyName;
// 如果这个函数还没有用作记忆的对象属性(该属性为一个对象直接量),则为其添加一个
fn.storage = fn.storage || {};
// 在‘storage’对象直接量中建立属性名称,用于保存和重新获取函数的执行结果。属性名称应该基于
// 传给函数的所有参数而设定,以确保属性名称是唯一的、基于所有可能输入参数组合的
// 我们借用Array类型的“join”方法,因为“arguments”本身就不是数组类型,它并不包含此方法
propertyName = Array.prototype.join.call(arguments, "|");
// 该键值(属性名称)是否存在于用作记忆的对象中
if(propertyName in fn.storage){
// 存在,则返回相关联的值以避免再次执行整个函数
return fn.storage[propertyName];
} else {
// 不存在,执行相关函数并将结果保存在用作记忆的对象中
fn.storage[propertyName] = fn.apply(this, arguments);
// 返回新保存的值,即函数执行的结果
return fn.storage[propertyName];
}
};
}
// 计算的方法函数
function getFactorial(num){
var result = 0,
index = 1;
for(; index <= num; index++){
result += index;
}
return result;
}
var getFactorialMemoized = memoize(getFactorial);
var time = new Date().getTime();
console.log(getFactorialMemoized(10000000));
console.log("first: " + (new Date().getTime() - time));
time = new Date().getTime();
console.log(getFactorialMemoized(5000000));
console.log("second: " + (new Date().getTime() - time));
time = new Date().getTime();
console.log(getFactorialMemoized(10000000));
console.log("third: " + (new Date().getTime() - time));
time = new Date().getTime();
console.log(getFactorialMemoized(5000000));
console.log("forth: " + (new Date().getTime() - time));