您的位置:首页 > Web前端 > JavaScript

高性能Javascript笔记

2016-04-21 18:43 501 查看
.) 下载并执行javacript会阻塞页面渲染,因此比较推荐js脚本放在页面底部,在</body>标签上边...
.) 尽量减少script标签。如果外链多个script文件,能合并就合并(利用合并的工具),同样适用内嵌的。
.) 动态脚本加载,无阻塞的比较好的解决方案:创建script DOM
比如:

var script = document.createElement("script");
script.type = "text/javascript";
//Firefox, Opera, Chrome, Safari 3+
//js文件src下载完的触发事件
script.onload = function(){
alert(1);
};
script.src = "jquery.js";
document.getElementsByTagName("head")[0].appendChild(script);


.) 另一种无阻塞载入,利用xhr对象获取脚本注入,这种方法不能跨域获取(--ajax

var xhr = new XMLHttpRequest();
xhr.open("get", "file1.js", true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
var script = document.createElement ("script");
script.type = "text/javascript";
script.text = xhr.responseText;// 相当于内联聊本的<script>标签
document.body.appendChild(script);
}
}
};
xhr.send(null);


事件委托:

dom如下所示,

span上都要有点击事件的反馈。如果在每个span上绑定click事件的话,当li很多时候,这样比较浪费性能。
事件绑定占用了处理时间,浏览器需要跟踪每个事件处理器,占用了更多内存。
此时可以使用事件委托。利用冒泡机制,在其父节点,比如只需要在ul上监听一个点击事件。然后判断节点哪个是哪个就ok了。

<div>
<ul id="ul">
<li>
<span id="a">aaaaa</span>
</li>
<li>
<span id="b">bbbb</span>
</li>
<li>
<span id="c">ccccc</span>
</li>
<li>
<span id="d">ddddd</span>
</li>
</ul>
</div>

<script type="text/javascript">
$('#ul').click(function(e){
var target = e.target;
// 只有点击的是span标签才触发事件
if(target.nodeName.toLowerCase() != 'span'){
return false;
}
var id = target.id; // 判断目标对象是哪个span
switch(id){
case 'a': alert(1);break;
case 'b': alert(2);break;
case 'c': alert(3);break;
case 'd': alert(4);break;
}

});
</script>


字符串连接;

str += "one" + "two";

str += "one";
str += "two";

str = str + "one" + "two";


第一行代码比较浪费,内存需要分配一个临时字符串来连接 "onetwo",然后再连str。

剩下两种方式,则不需要内存额外分配变量。

作用域链和原型链得知,一个全局变量在局域使用,最好是赋值给局域变量。链上远的变量查找更耗时,更消耗性能。

在操作dom集合(类数组而不是数组)的时候,涉及到length,尽量把这个集合的length赋值给一个变量,然后在循环里使用这个变量。遍历集合没有遍历数组快。

大多数时候没必要使用eval()和Function(),每次调用eval()时都要创建一个新的解释器/编译器示例。
尽量避免使用他们。至于setTimeout()和setInterval(),建议传入函数而不是字符串作为第一个参数。比如:

setTimeout(function(){
sum = a+b;
}, 100);


使用Object/Array时,建议使用直接量,这样更快。
比如:

var obj = new Object();
obj.name = 'a';
obj.age = 12;

// 更推荐这种方式:
var obj = {
name: 'a',
age: 12
};

// ============
// 数组比如:
var arr = new Array();
arr[0] = 'a';
arr[1] = 'b';

// 更推荐这种:
var arr = ['a', 'b'];


不要重复工作:
比如根据一个判断(比如这里的 a 和 b 大小比较)处理一个逻辑:

var a=1;
var b=2;
function test(){
if(b>a){
xxx;// 几行代码
} else {
yyy;//
}
}


比如这个 test() 函数在页面上可能会频繁遭到调用,那么每次都要去判断 a 和 b 的大小(如果是更复杂的逻辑判断,那么频繁调用一定会浪费性能)。那么不如在代码中重新覆盖这个 test() 函数:

function test(){
if(b>a){
test = function(){// 重新给test赋值
xxx;
};
} else {
test = function(){
yyy;
};
}
test();// 当然结尾不要忘记执行
}


这样的话,下一次再去调用这个test()的话,直接就是了。

数字运算的话,可以多考虑下,是否可以按位运算。比如奇数偶数这个...和1按位与操作。

尽量使用原生js,比较原生的都是js引擎低级编程语言编译好的,要更快。

Ajax:

常用的向服务器请求数据的方法:
1. XMLHttpRequest(XHR) 最常用的技术
2. 动态脚本注入
3. Multipart XHR

1). xhr(ajax常用技术,IE低版本要使用 ActiveXObject )是最常用的,它允许异步发送和接收数据。浏览器支持好,get、post方式均可,可以读取http响应头信息和响应文本。缺点不能跨域。
代码:

var url = '/data.php?a=1&b=2';
var req = new XMLHttpRequest();

req.onreadystatechange = function(){
if(req.readyState === 4){// 4表示整个响应接收完毕;3表示接收到部分信息,还没完
var responseHeaders = req.getAllResponseHeaders();// 获取响应头信息
var data = req.responseText;// 获取响应文本
// 逻辑处理
// ...
}
}

req.open('GET', url, true);// true表示异步
req.setRequestHeader('', '');// 可以设置请求头信息
req.send(null);// 发送请求


2). 动态脚本注入
这个方法利用动态创建 script 元素来请求数据。它克服了xhr最大限制:可以跨域请求。这当然算是个Hack。

xhr的缺点:不可以设置请求头信息;也只能使用get方式;需要等这个脚本下载完,才能访问它们;返回的数据需要封装在函数里。
因为响应信息是脚本标签的源码(script),因此他必须是可执行的javascript代码,所以数据格式需要封装在函数里,或者说调用一个函数。
代码:

var scriptEle = document.createElement('script');
scriptEle.src = 'http://xxx/test.js';// 可以请求与当前脚本所在不同域的文件。
document.getElementsByTagName('head')[0].appendChild(scriptEle); // 在head头部插入脚本
function callfun(data){
// 接收到服务端过来的 data
alert(data.a);
}

// test.js 文件内容
callfun({a:1,b:'qq'});// 数据被包含在回调函数里。


向服务器传输数据:
一种xhr的技术,还有一种信标的方法。
所谓信标,就是创建一个Image对象,利用属性src向服务器传输数据。然而这种方法,效率虽高,但是存在局限性,一般只是像服务器传输数据,而不关心返回结果(当然服务端的确可以返回一个图片,然后前端根据图片的比如宽度来判断逻辑,这个宽度也可以算是服务端的返回状态。不过一般使用这种方法,不考虑服务端返回结果...),而且src表示也只能以get方式传输,并且参数长度也有所限制。
代码:

(new Image()).src = 'http://www.test.com/xxx.php?a=1&b=x';// 传输了a、b两个参数值过去


-
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: