写出高性能的javascript代码

JavaScript代码的速度被分成两部分:下载时间和执行速度。

Web浏览器下载的是js源码,因此所有长变量名和注释都回包含在内。这个因素会增加下载时间。1160是一个TCP-IP包中的字节数。最好能将每个javascript文件都保持在1160字节以下以获得最优的下载时间。

   由于这个原因,要删除注释、删除制表符和空格、删除所有的换行、将长变量名缩短。 遵循这4条比较困难。因此用外部程序(ECMAScript Cruncher)来帮助我们。

要运行ESC,必使用Windows系统,打开一个控制台窗口,然后使用以下格式的命令:

cscript ESC.wsf -l [0-4] -ow outputfile.js inputfile1.js [inputfile2.js]

第一部分,cscript,是Windows Shell脚本解释程序。文件名ESC.wsf是ESC的程序本身。然后是压缩级别,一个0到4的数值。-ow选项表示下一个参数是优化后输出的文件名。最后,剩下的参数是要进行优化的JavaScript文件,可以有多个文件(多个文件在优化后后会按顺序放到输出文件中)。

0 —— 不改变脚本,要将多个文件拿到单个文件中时用用。

1 —— 删除所有的注释。

2 —— 除等级1外,再删除额外的制表符和空格。

3 —— 除等级2外,再删除换行。

 

4 —— 除等级3外,再进行变量名替换。

ESC擅长把变量名替换成无意义的名称,它还具有一定的智能,进行私有对象先进性和方法名的替换(由名称前后加上两个下划线表示),所以私有特性和方法依然保持其私有性。

ESC不会更改构造函数名、公用属性和公用方法名,所以无需担心。但要注意的是如果某个JavaScript引用了另一个文件中的构造函数,4级优化会把对构造函数的引用替换成无意义的名称。解决方法是将两个文件合成一个文件,这样就会保持构造函数的名称。

====================================

   其他减少字节数的方法还有几个。      1.因为在javascript语言中 true等于1,false等于0。因此,脚本包含的字面变量true都可以用1来替换,而false可以用0来替换。 例如:

var bFound = false; for (var i = 0; i < aTest.length && !bFound; i++) { if (aTest[i] == vTest) {   bFounde = true; } }

var bFound = 0; for (var i = 0; i < aTest.length && !bFound; i++) { if (aTest[i] == vTest) {   bFounde = 1; } }

  2.缩短否定检测

if (oTest != undefined) {   //do someting } if (oTest != null) { //do someting } if (oTest != false) {   //do someting }

可以替换成

if (!oTest) { //do something }

3.减少语句数量 var iFive = 5; var sColor = "blue";

可以为

var iFive = 5, sColor = "blue";

var sName = aValues[i]; i++; //可以替换成 var sName = aValues[i++];

 

◆字符串的使用

在IE6和IE7中因字符串级联导致的主要问题是垃圾回收性能,虽然这些问题在IE8中已经得到解决,但如果你的用户大部分仍然在使用IE或IE7,你就得格外注意这个问题了。看一个例子先:

var veryLongMessage = "This is a long string that due to our strict line length limit of" + maxCharsPerLine + " characters per line must be wrapped. " + percentWhoDislike + "% of engineers dislike this rule. The line length limit is for " + " style purposes, but we don't want it to have a performance impact." + " So the question is how should we do the wrapping?";

可以使用连接代替级联:

var veryLongMessage = ["This is a long string that due to our strict line length limit of", maxCharsPerLine, " characters per line must be wrapped. ", percentWhoDislike, "% of engineers dislike this rule. The line length limit is for ", " style purposes, but we don't want it to have a performance impact.", " So the question is how should we do the wrapping?"].join();

 

◆与此类似,在条件语句中使用级别也是很低效的,错误的做法:

var fibonacciStr = "First 20 Fibonacci Numbers "; for (var i = 0; i < 20; i++) { fibonacciStr += i + " = " + fibonacci(i) + " "; }

最好的方法是:

var strBuilder = ["First 20 fibonacci numbers:"]; for (var i = 0; i < 20; i++) { strBuilder.push(i, " = ", fibonacci(i)," "); } var fibonacciStr = strBuilder.join("");

◆定义类函数

下面的函数是低效的,因为每次构造baz.Bar的实例时,会创建一个新的函数和闭包:

baz.Bar = function () {

  // constructor body this.foo = function () {

  // method body }; };

正确的方法是:

baz.Bar = function () {

  // constructor body this.foo = function () {

  // method body }; }; baz.Bar = function () {

  // constructor body }; baz.Bar.prototype.foo = function () {

  // method body };

使用这个方法时,无论baz.Bar构造了多少个实例,都只会为foo创建一个函数,而且不会创建闭包。

◆初始化实例变量

使用实例变量值类型初始值初始化实例变量声明,如数值、布尔值、空值、未定义或字符串,这样可以避免每次调用构造器时运行不必要的初始化代码。还是来看一个例子:

foo.Bar = function () { this.prop1_ = 4; this.prop2_ = true; this.prop3_ = []; this.prop4_ = "blah"; };

可以代替为:

foo.Bar = function () { this.prop3_ = []; }; foo.Bar.prototype.prop1_ = 4; foo.Bar.prototype.prop2_ = true; foo.Bar.prototype.prop4_ = "blah";

◆避免使用with

避免在代码中使用with,它会影响到性能,因为它修改了范围链,因此需要花费更多时间到其它范围去查找。

 

◆尽可能避免使用全局变量和函数. 全局的变量和函数其实等价于 window 对象的属性/方法, 访问速度自然会慢.

var myvar = 0; // 336ms window.myvar = 0; // 2383ms

var myfunc = function(){} // 3515ms window.myfunc = function(){} // 10151ms

◆尽量避免用 new 操作符创建函数. 可能通过 new 创建的函数还需要额外地对函数内容字符串进行解析操作.

function f(){}; // 277ms var f  = function(){} // 3085ms var f = new Function("") // 13275ms

◆尽量避免使用 eval() 执行代码. 原因同 new 创建函数的操作.

var myfunc = function(){} // 3408ms eval("var myfunc = function(){}"); // 9140ms

 

◆少使用 new 操作符创建数组. 原因同 new 创建函数的操作. 特别在有大量数据时更为明显

a = [1, 2, 3]; // 4360ms a = new Array(1, 2, 3); // 5000ms

 

◆尽量避免使用 push() 和 pop() 处理数组数据.

a[i] = value; // 1270ms a.push(value); // 3240ms

 

◆使用对象代替数组存储数据对性能略有影响. 也许是因为 Javascript 的数组是个带有扩展方法和属性的对象, 而不像 VBScript 那样是单纯的数据结构.

a[i] = value; // 1270ms obj[property] = value; // 960ms

 

◆使用 ++ 代替 x = x+1 和 +=. 事实上 ++ 并不比 + 和 += 快很多, 但是在大量的操作时就会体现出其优势. 而 + 和 += 几乎没有性能差别. 同理对 -- 和 - 以及 -= 适用.

x++; // 378ms x = x+1; // 406ms x += 1; // 406ms

 

◆使用局部变量缓存对象属性和函数指针 例如在遍历数组时缓存数组长度, 事实上获取 Javascript 的数组长度等于调用一个方法函数(大部分Javascript 引擎是这样实现的). 如果对 HTML DOM 进行操作, 那么优化的效果会非常明显.

for(var i=0;i<arr.length;i++){ ... } // 162ms

var length = arr.length; for(var i=0;i<length;i++){ ... } // 156ms

或者使用局部变量缓存一个外部函数(具体效果视代码复杂度而定). 如果代码块中要多次调用一个外部函数或变量, 那么缓存的效果会非常明显.

function test(){ ... } function run1(){  test(); } function run2(){  var t = test;  t(); }
run1(); // 98ms run2(); // 80ms

 

转自:http://jiangzhengjun.javaeye.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值