In reading this / 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.
In reading this http://www.html5rocks./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.
Share Improve this question edited Jan 25, 2014 at 8:55 Brian McGinity asked Jan 25, 2014 at 8:06 Brian McGinityBrian McGinity 5,9456 gold badges39 silver badges46 bronze badges 5- null is of type object – Patrick Evans Commented Jan 25, 2014 at 8:07
- that's good, because it's a lot easier to check if something is null rather than {} – Brian McGinity Commented Jan 25, 2014 at 8:08
- actually you cannot check against {}, well you can but you would always get false, as that creates a new object on the fly, for instance {} === {} evaluates to false. – Patrick Evans Commented Jan 25, 2014 at 8:15
- Yeah, I know...it is a lot harder and seems like longer to check for an empty object. – Brian McGinity Commented Jan 25, 2014 at 8:19
-
I'm not sure about the performance issues but an alternative would maybe to declare
x
as an empty object and only add certain properties if they have a real value. Then you can check whether a property is set or not using.hasOwnProperty()
for instance. – basilikum Commented Jan 25, 2014 at 8:43
2 Answers
Reset to default 6Intrigued 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/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]
bees...
var x = {
alpha: {a:1, b:true},
bravo: 13,
charlie: true,
delta: [1,2,3]
};