简体   繁体   中英

Javascript declaring variables - best practice

In reading this http://www.html5rocks.com/en/tutorials/speed/v8/ it makes sense that changing the type of variable at runtime forces browsers to work harder than when keeping them consistent.

So does that mean this is not a good idea:

 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'

Because here the types started as null, then got changed to object, int, boolean arrary.

And for the sake of simplicity, afterwards these types never change.

Or is this more efficient:

 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'

I can understand changing types from say a number to an array is not a good idea. What about changing from null into a type once during execution?

The books and blogs I have read mostly say to define variables with null (as opposed to undefined) when the values are only known at runtime. At face value, this seems wrong, as defining with their empty type avoids a type change.

Intrigued by this question, I set up a fiddle to look at the performance of some different use cases.

Open console to view data in this fiddle
http://jsfiddle.net/kmiklas/MFNak/14/

  • There seems to be little difference between no initialization, initializing to null, and initializing to a number.
  • With the exception of numbers, there is a perf loss by initializing variables to the intended type (second example in original post).
  • From these data, it stands to reason that initializing to nothing is the best option.

Typical results from Chrome v32 with 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 
~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Code is rather lengthy, but included below, per SO requirements.

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

Edit:

Keep in mind that I only tested in Chrome 32. To accurately draw this conclusion, it would be best to load this fiddle and see results in the more popular desktop and mobile browsers; particularly, IE and Safari Mobile.

At initialization, all javascript variables are hoisted to the top of the scope with the value of undefined . It's not until a variable's value is assigned that a specific type can be assigned.

So what you're doing here is effectively reassigning the value and type of your variable twice. The performance cost is likely negligible, however the preferred practice to declare an object whose values are not known is with an object literal:

var x = {};

If you try to access a property of an object that doesn't exist, you'll get undefined (which is just as easy to test for as null ). However, if as you say the properties are known before runtime then there's no reason not to assign those properties straight away, so...

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

becomes...

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM