Javascript声明变量 - 最佳实践

时间:2014-01-25 08:06:33

标签: javascript performance google-chrome

在阅读这篇http://www.html5rocks.com/en/tutorials/speed/v8/时,有必要在运行时更改变量的类型,迫使浏览器更加努力地工作,而不是保持它们的一致性。

这是否意味着这不是一个好主意:

 var x = {
   alpha:    null,
   bravo:    null,
   charlie:  null,
   delta:    null,
   echo:     null
 }

 x.alpha   = {a:1, b:true}
 x.bravo   = 13
 x.charlie = true
 x.delta   = [1,2,3]
 x.echo    = 'abc'

因为这里的类型从null开始,然后变为object,int,boolean arrary。

为了简单起见,之后这些类型永远不会改变。

或者效率更高:

 var x = {
   alpha:    {},
   bravo:    0,
   charlie:  false,
   delta:    [],
   echo:     ''
 }

 x.alpha   = {a:1, b:true}
 x.bravo   = 13
 x.charlie = true
 x.delta   = [1,2,3]
 x.echo    = 'abc'

我可以理解从数字到数组的更改类型不是一个好主意。如何在执行期间从null更改为类型?

我读过的书籍和博客主要是说,当值只在运行时知道时,用null定义变量(而不是undefined)。从表面看,这似乎是错误的,因为用空类型定义可以避免类型更改。

2 个答案:

答案 0 :(得分:6)

对这个问题感兴趣,我设置了一个小提琴,看看一些不同用例的表现。

打开控制台以查看此小提琴中的数据
http://jsfiddle.net/kmiklas/MFNak/14/

  • 没有初始化,初始化为null和初始化为数字之间似乎没什么区别。
  • 除数字外,通过将变量初始化为预期类型(原始帖子中的第二个示例)会导致性能损失。
  • 从这些数据中可以看出,初始化为零是最好的选择。

Chrome v32的典型结果,n = 100000000:

number no init: 97.070ms 
number init to null: 98.023ms 
number init to number: 97.246ms 
array no init: 457.494ms 
array init to null: 458.301ms
array init to number: 455.166ms 
array init to array: 836.710ms 
object no init: 508.268ms 
object init to null: 512.312ms 
object init to object: 754.562ms 
number to object: 455.733ms 
array to object: 834.169ms 
object to array: 751.498ms 
~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

代码相当冗长,但根据SO要求包含在下面。

n = 100000000;
console.time("number no init");
    for (var i = n; i >= 0; i--) { var x; x = 42; };
console.timeEnd("number no init");

console.time("number init to null");
    for (var i = n; i >= 0; i--) { var x = null; x = 42; };
console.timeEnd("number init to null");

console.time("number init to number");
    for (var i = n; i >= 0; i--) { var x = 1; x = 42; };
console.timeEnd("number init to number");

console.time("array no init");
    for (var i = n; i >= 0; i--) { var a; a = [42]; };
console.timeEnd("array no init");

console.time("array init to null");
    for (var i = n; i >= 0; i--) { var a = null; a = [42]; };
console.timeEnd("array init to null");

console.time("array init to number");
    for (var i = n; i >= 0; i--) { var a = 1; a = [42]; };
console.timeEnd("array init to number");

console.time("array init to array");
    for (var i = n; i >= 0; i--) { var a = []; a = [42]; };
console.timeEnd("array init to array");

console.time("object no init");
    for (var i = n; i >= 0; i--) { var a; a = {n:42}; };
console.timeEnd("object no init");

console.time("object init to null");
    for (var i = n; i >= 0; i--) { var a = null; a = {n:42}; };
console.timeEnd("object init to null");

console.time("object init to object");
for (var i = n; i >= 0; i--) { var a = {}; a = {n:42}; };
console.timeEnd("object init to object");

console.time("number to object");
    for (var i = n; i >= 0; i--) { var a = 1; a = {n:42}; };
console.timeEnd("number to object");

console.time("array to object");
    for (var i = n; i >= 0; i--) { var a = []; a = {n:42}; };
console.timeEnd("array to object");

console.time("object to array");
for (var i = n; i >= 0; i--) { var a = {}; a = [42]; };
console.timeEnd("object to array");
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~');

编辑:

请注意,我仅在Chrome 32中测试过。要准确得出这个结论,最好加载这个小提琴并在更受欢迎的桌面和移动浏览器中查看结果;特别是IE和Safari Mobile。

答案 1 :(得分:3)

在初始化时,所有javascript变量都会被提升到范围的顶部,其值为undefined。直到为变量赋值,才能分配特定类型。

所以你在这里做的是有效地重新分配变量的值和类型两次。性能成本可能可以忽略不计,但声明其值未知的对象的首选做法是使用对象文字:

var x = {};

如果您尝试访问不存在的对象的属性,您将得到未定义(这与null一样容易测试)。但是,如果您说在运行时之前已知 属性,则没有理由不立即分配这些属性,因此......

 x.alpha = {a:1, b:true}
 x.bravo = 13
 x.charlie = true
 x.delta   = [1,2,3]

...变为

var x = {
  alpha:    {a:1, b:true},
  bravo:    13,
  charlie:  true,
  delta:    [1,2,3]
};