Javascript代码优化

原文 https://developers.google.com/speed/articles/optimizing-javascript

客户端的javascript可以使你的app更加灵活与动态变化,但是浏览器解释代码时,可以引入低效率,而且各个浏览器的区别也很大。如下我们将讨论一些优化javascript代码的方法。


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?';

Working with strings

字符串的连结能够引起IE67垃圾回收的性能问题。尽管在IE8中,这个问题已经被解决了,甚至比其他浏览器更加高效,譬如chrome。但是有很多用户仍然在使用IE6,这个问题应该注意。

取代连结,采用join

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();

同样,通过条件或者循环方式以连结的方式建立string是非常低效的。错误的方式如下


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('');

Buildingstrings with portions coming from helper functions

以传stringbulder方式建立string,注意的是避免临时string的产生。例如,假设buildMenuItemHtml_ 能够把变量转化为string。不好的代码如:


var strBuilder = [];
for (var i = 0, length = menuItems.length; i < length; i++) {
  strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();

良好的代码为:


var strBuilder= [];
for(var i = 0, length = menuItems.length; i < length; i++) {
  this.buildMenuItem_(menuItems[i],strBuilder);
}
varmenuHtml = strBuilder.join();

Definingclass methods

如下code的效率很低,每当baz.Bar的实例a被构造,foo的函数以及闭包随之产生

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

更好的方法为:


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

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

Initializinginstance variables

把变量的声明以及初始化放到实例的prototype里,以此避免当构造函数被调用时,变量每次都被初始化


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

采用如下的code


foo.Bar =function() {
  this.prop3_= [];
};

foo.Bar.prototype.prop1_= 4;

foo.Bar.prototype.prop2_= true;

foo.Bar.prototype.prop4_= 'blah';

Avoidingpitfalls with closures

闭包的缺点如下:

·        They are the most common source of memory leaks.

·        Creating a closure is significantly slower then creating aninner function without a closure, and much slower than reusing a staticfunction. For example:


function setupAlertTimeout() {
  varmsg = 'Message to alert';
  window.setTimeout(function(){ alert(msg); }, 100);
}

效率低于


function setupAlertTimeout() {
  window.setTimeout(function(){
    varmsg = 'Message to alert';
    alert(msg);
  },100);
}

效率低于


function alertMsg() {
  varmsg = 'Message to alert';
  alert(msg);
}

functionsetupAlertTimeout() {
  window.setTimeout(alertMsg,100);
}


var a = 'a';

functioncreateFunctionWithClosure() {
  varb = 'b';
  returnfunction () {
    varc = 'c';
    a;
    b;
    c;
  };
}

varf = createFunctionWithClosure();
f();

f被调用了,ab慢,他们都比c慢。

Avoiding with



你可能感兴趣的:(Javascipt)