JS: How to use abbreviations for full named variables? - javascript

I prefer to declare all global variables at the beginning of my code using self-explanatory, full-named variables:
var $interval_start_dates = []; // date intervals
var $interval_end_dates = [];
var $interval_start_milli = []; // convert dates to milliseconds
var $interval_end_milli = [];
var $interval_start_milli_sorted = []; // sort millisecond dates
var $interval_end_milli_sorted = [];
This naming convention often results in long variable-names which I find unhandy when using them in the code. Therefore I also prefer to use abbreviations for the variables in the code:
var _isd = $interval_start_dates;
var _ied = $interval_end_dates;
var _ism = $interval_start_milli;
var _iem = $interval_end_milli;
var _isms = $interval_start_milli_sorted;
var _iems = $interval_end_milli_sorted;
My questions in this regard are the following:
(1) Is it possible to output the intermediate variable (e.g. $interval_start_dates) using the abbreviation (e.g. _isd)?
(2) Does this naming convention result in worse performance of the code (e.g. speed) and if so is there a better way to use abbreviations?
One remark: I know that I could just use comments to inform about the full name of an abbreviated variable. But this means that I would have to repeat those comments many times in my code. I am looking for a more "slick" solution which allows me to use for example console.log to display the full name of a variable (if this is possible).

why not use some data structure. the advantage is the more readable format and you can use abbreviation for accessing the variables.
var interval = {
start: {
dates: [], // date intervals
milli: [], // convert dates to milliseconds
milli_sorted: [] // sort millisecond dates
},
end: {
dates: [],
milli: [],
milli_sorted: []
}
};
// use
var ie = interval.end;
alert(ie.dates);

Is it possible to output the intermediate variable (e.g. $interval_start_dates) using the abbreviation (e.g. _isd)?
Yes. They both refer to the same array, so it doesn't matter which you use to output the array.
(2) Does this naming convention result in worse performance of the code (e.g. speed) and if so is there a better way to use abbreviations?
No. They both refer to the same array, each is just as direct a reference as the other.
But, there are other potential issues. For instance, if you had need of filtering or mapping those arrays, it would be really easy to update one reference and forget the other, e.g.:
_isd = _isd.filter(function(entry) { return entry.foo < bar; });
// OOOPS! Now `_isd` and `$interval_start_dates` don't refer to the same array anymore!
If it's just typing out the names, any good IDE can make that easier for you.
I am looking for a more "slick" solution which allows me to use for example console.log to display the full name of a variable (if this is possible).
I'm not sure what you're asking here, but if you mean that you want to use _isd somewhere (for instance, a function) and have that function display $interval_start_dates in its output instead of _isd, then you can't (reasonably) do that. There is no link between _isd and $interval_start_dates, other than that they refer to the same array. But then, you can't do that anyway — if you passed $interval_start_dates into a function, it still can't infer the name of it, because the function's argument that receives the value isn't linked in any way to $interval_start_dates (other than that they refer to the same array).
Side note: If all of these things are arrays, and you want to have some way of knowing a "name" of the array based on an array reference, you can take advantage of the fact that standard arrays in JavaScript aren't really arrays at all, they're just objects and assign them a property with the name in, for instance:
var $interval_start_dates = []; // date intervals
$interval_start_dates.name = "$interval_start_dates";
// ...
var _isd = $interval_start_dates;
console.log(_isd.name); // "$interval_start_dates"
If you do that, be sure you're not using for-in to loop through the arrays (but there are better ways anyhow). Or use Object.defineProperty to define the name instead:
var $interval_start_dates = []; // date intervals
Object.defineProperty($interval_start_dates, "name", {
value: "$interval_start_dates"
});
...and properties added that way are non-enumerable by default.

Performance-wise this does not matter. Your code will becoming less readable though. So you will have to decide what is more important to you: readability or coding faster. You can achieve both though by using an IDE which autocompletes your variable names.
Also, most of the time your variable names can be made shorter while not losing any meaning, for example:
var $interval_start_milli could be changed to var interval_start_ms or even var start_ms, since an interval has a start and an end, which would mean you would either have var interval_ms or start_ms and end_ms. Where var interval_ms is an array of objects with a start and an end property.
But that also depends on which other global variables you have declared though.
Another thing is that you shouldn't rely on global variables too much in javascript.

Related

Is array better than objects for storing and searching key value pairs in javascript?

I am fetching data from db and storing it in an array in key value pair, so that i can get values of respective keys as below
var test = [];
for () //fetching and storing from db
{
test[key_array[i]] = "value i";
.
.
.
}
test["id_1"] = "value 1"; //to get the value of id_<number>
we can achive this though objects too. I wanted to know which is the better option to consider, if we want a fast and optimized code
Is array better than objects for storing and searching key value pairs in javascript?
No. In fact, you're not using the array as an array, you're using it as an object. You could literally change your
var test = [];
to
var test = {};
// or
var test = Object.create(null); // To avoid it having a prototype
and it would do the same thing you're seeing now:
var test = {};
test["id_1"] = "value_1";
console.log(test["id_1"]);
var test2 = Object.create(null);
test2["id_2"] = "value_2";
console.log(test2["id_2"]);
(And you should change it, since using an array only for its object features is confusing to people maintaining your code.)
[] is a property accessor that accepts the property name as a string. (We use it with standard arrays as well, using numbers, but in theory they get converted to strings before the property is looked up, because standard arrays aren't really arrays at all¹.)
In ES2015+, of course, you'd probably use a Map, not an object:
const test = new Map();
test.set("id_1", "value_1");
console.log(test.get("id_1"));
¹ That's a post on my anemic little blog.
Arrays, are just a kind of object specialized for storing sequences of things. If you evaluate typeof [], it produces "object".
https://eloquentjavascript.net/04_data.html#h_cqg63Sxe3o
The idea of an array is store sequences of data with the same type or logic structure. Thus, is logic put the data come from a db into an array.
Note that you should avoid this because it can become very confusing :
var test = [];
test["id_1"] = "value_1";
test[-1] = "value_0";
console.log(test[-1],test["id_1"]);
console.log(test.length,Array.isArray(test));
It lets you think that test is an array (and it is) but test[-1] and test["id_1"] are not part of the array (that's why Array.isArray(test) returns true, but test.length is still equal to 0. See explanation on link provided by mister T.J. Crowder

Javascript Hashing Two Numbers

I have two numbers in javascript.
They are integral coordinates.
I also have an object: var regions = {};
I'd like to be able to access specific objects as quickly as possible.
E.g. there could be an object at (5,-2)
What's a fast way of creating unique hashes, that do not clash, for two numbers like this?
I'm assuming the "specific objects" you want to access are referenced by properties on regions. Object properties in JavaScript are named either by string names or by Symbol names. You'd be using strings in this case.
Since it's going to be by string, the simple solution is just create a string, and look it up with that:
var obj = regions[num1 + "," + num2];
That leaves it up to the JavaScript engine to do a good job looking up the property. JavaScript engines are very good (read: fast) at this, because they have to do it a lot.
How the engine does the lookup will depend in some measure on how the regions object is created. Wherever possible, modern engines will create objects that are effectively micro-classes and provide very quick resolution of property names. If you do certain things (like using delete on one of the properties), a modern engine may fall back to "dictionary" mode where it uses a hash lookup. This is still fast, just not as fast as the optimized form.
I doubt you'll find a quicker way that that. In theory, if region were a contiguous array where elements referenced contiguous arrays, the JavaScript engine could make those true arrays under the covers, and one of your example numbers is negative which would prevent a true array from being used. And you'd still be doing two lookups (the first number, then the second), and there's no guarantee it would be faster. It would certainly be more complicated.
As you've said you'll receive the information in dribs and drabs, I'd go with a simple compound string key until/unless you have a performance problem with that solution, then look at trying to get contiguous arrays happening on your target engines (converting those negative indexes into something else, which could be problematic). I doubt you'll find that the lookup is every the bottleneck.
You can use array notation:
var regions = {}
regions[[5,-2]] = myObject;
regions[[5,-2]]; // myObject
Object keys can't be arrays, so under the hood [5,-2] will be stringified to "5,-2". But I think that using array notation is more pretty than stringifying manually.
Example:
var regions = {
'5,-2': { ... },
'1,3': { ... }
};
and then if you have the 2 numbers you could easily generate the key and access the corresponding object:
var x = 5;
var y = -2;
var obj = regions[x + ',' + y];
I used two function encode and decode.
var x = 10;
var y = -3.2;
function encode(x, y) {
return x + ',' + y;
}
function decode(code) {
var xy = code.split(',');
return [+xy[0], +xy[1]];
}
var code = encode(x, y);
console.log(code);
var xy = decode(code);
console.log(xy);
The code can be used as dict key value.

Javascript Object inside of Object

I'm working with phylogentic trees and I want an object for the tree itself and then an object for each species, 4 species total. I'm trying to have the tree contain the species objects under tree.leaf and then assign an array of attributes to each species but through the tree object, because I'm randomizing the order of the species so I can't depend on species names but I can use leaf placement(Hope that makes sense). I'm having trouble updating the html, a div inside a table though.
Simplified Version:
var tree = new Object();
var speciesA = new Object();
tree.leaf1 = speciesA;
//Not sure if this next line assigns to speciesA or what exactly happens
tree.leaf1.attributes = new Array("Attr1","Attr2",etc);
var count = 1;
for(attr in speciesA.attributes)
{
//There are 4 divs per speices to display attributes
document.getElementById("A"+String(count)).innerhtml = speciesA.attributes[attr];
count++;// used to specify divs ie A1 = attribute1, A2 = attribute2 etc
}
So I guess my main question is will this work/do what I think it does?
If needed I can pastebin my html and full js files.
What you have should work, but it can be written a bit cleaner. I would suggest this:
var tree = {
leaf1: {attributes: ["Attr1", "Attr2"]}
};
var attributes = tree.leaf1.attributes;
for (var i = 0; i < attributes.length; i++) {
document.getElementById("A"+(i+1)).innerHTML = attributes[i];
}
Things I changed:
Used a javascript literal to make the definition a lot more compact
Used {} and [] for defining arrays and objects rather than new Object() and new Array().
Used for (var i = 0; i < xxx.length; i++) syntax to iterate array elements only, not all properties. This is the "safe" way to iterate elements of an array.
Remove the String(count) as it is not needed. Javascript will auto-convert a number to a string when adding to another string.
Cached the value of the attributes array to save having to deep reference it each time.
Removed separate count variable as the for index can be used
To answer one of your other questions, when you do this:
tree.leaf1 = speciesA;
you have assigned a "reference" to speciesA to tree.left1. A reference is like a pointer. It is not a copy. So, the both refer to exactly the same object. Any change you make to speciesA or to tree.leaf1 is make a change to the exact same object.
So, when you then do this:
//Not sure if this next line assigns to speciesA or what exactly happens
tree.leaf1.attributes = new Array("Attr1","Attr2",etc);
you are indeed modifying the speciesA object since speciesA and tree.leaf1 point to the same object.
In javascript, arrays, objects and strings are assigned by reference. That means that when you assign one to a variable, it just points to the original object. A copy is not made. So, change the object via either either one will change the other (since they both point to the same object). Strings are immutable (a string is never actually changed). Things that feel like modifications to a string always just return a new string so this aspect of javascript doesn't affect strings so much. But, it is very important to know that arrays and objects are assigned by reference.

What are the speed diferences between object's property access and normal variable access?

Before fully defining my question, I must say that >>this question/answer<< doesn't answer my problem, and I have proven it to myself that the given answer doesn't match at all with the actual effect of property vs. variable or cached property (see below).
I have been using HTML5 canvas, and I write raw pixel blocks many times in a second in a 640x480 area.
As advised by some tutorials, it is good to cache the .data property of an ImageData variable (in this case, it would be _SCimgData).
If I cache that property in SC_IMG_DATA, I can putImageData repeatedly in the Canvas with no problem; but if I repeatedly access it directly with _ScimgData.data, the slow-down of the code is noticieable (taking nearly 1 second to fill a single 640x480 Canvas):
var SomeCanvas = document.getElementById("SomeCanvas");
var SCContext = SomeCanvas.getContext("2d");
var _SCimgData = SomeCanvas.getImageData(0, 0, 640, 400);
var SC_IMG_DATA = _SCimgData.data;
Now I have the following doubt:
Would my code be as slow for other kinds of similar accesses?
I need an array of objects for a set of functions that can have several "instances" of an object (created by a regular utility function), and that need the index of the instance in an array of objects, either to create/initialize it, or to update its properties.
My concrete example is this:
var objArray=new Array();
var objArray[0]=new Object();
objArray[0].property1="some string property";
for(var x=0; x<65536; x++)
doSomething(objArray[0].property1, objIDX=0);
Would that code become as unacceptably slow as in the Canvas case, if the properties and functions contained in some properties are called very intensively (several times in a single milisecond, of course using setInterval and several "timer threads" to avoid locking the browser)?
If so, what other alternative is there to speed up access for the different properties of several objects in the main object array?
EDIT 1 (2012-08-27)
Thanks for the suggestions. I have up-voted them since I suspect they will be useful for the project I'm working on.
I am thinking in a combination of methods, using mainly Arrays instead of Objects to build an actual array of "base objects", and addressing array elements by numbers (arr[0]) instead of string array keys (arr["zero"]).
var OBJECTS_SIZE=10
var Obj_Instances=new Array();
Obj_Instances[0]="property or array 1 of Object 0";
Obj_Instances[1]=new Array();
Obj_Instances[1][0]=new ArrayBuffer(128);
Obj_Instances[1][1]=new DataView(Obj_Instances[1][0]);
Obj_Instances[2]="property or array 3 of Object 0";
Obj_Instances[3]=function(){alert("some function here")};
Obj_Instances[4]="property or array 5 of Object 0";
Obj_Instances[5]="property or array 6 of Object 0";
Obj_Instances[6]=3;
Obj_Instances[7]="property or array 8 of Object 0";
Obj_Instances[8]="property or array 9 of Object 0";
Obj_Instances[9]="property or array 10 of Object 0";
Obj_Instances[10]="property or array 1 of Object 1";
Obj_Instances[11]=new Array();
Obj_Instances[11][0]=new ArrayBuffer(128);
Obj_Instances[11][1]=new DataView(Obj_Instances[11][0]);
Obj_Instances[12]="property or array 3 of Object 1";
Obj_Instances[13]=function(){alert("some function there")};
Obj_Instances[14]="property or array 5 of Object 1";
Obj_Instances[15]="property or array 6 of Object 1";
Obj_Instances[16]=3;
Obj_Instances[17]="property or array 8 of Object 1";
Obj_Instances[18]="property or array 9 of Object 1";
Obj_Instances[19]="property or array 10 of Object 1";
function do_Something_To_Property_Number_6(objIdx)
{
//Fix the index to locate the base address
//of the object instance:
///
objIdx=(objIdx*OBJECTS_SIZE);
Obj_instances[objIdx+6]++; //Point to "Property" 6 of that object
}
I would have, say an "instance" of an "object" that takes up the first 10 array elements; the next "instance" would take the next 10 array elements, and so on (creating the initialization in a custom "constructor" function to add the new block of array elements).
I will also try to use jsPerf and JSHint to see which combination result better.
To answer your "doubts", I suggest using JSPerf to benchmark your code. One can't really tell by code alone if the procedure is faster than another unless tested.
Also, I suggest you use the literal notation for arrays and objects instead of the new notation during construction:
var objArray=[
{
property : 'some string property'
}, {
...
},
];
Also, based on your code, it's better to have this since you are using the same object per iteration:
var obj = objArray[0].property1,
objIDX = 0;
for(var x=0; x<65536; x++){
doSomething(obj,objIDX);
}
I realise this is not quite answering your question (as it has already been answered), however as you seem to be looking for speed improvements in regard to function calls that happen thousands of times (as others who find this might also be doing). I thought I'd include this here as it goes against assumptions:
An example function:
var go = function (a,b,c,d,e,f,g,h) {
return a+b+c+d+e+f+g+h;
}
The following is how you would normally call a repetitive function:
var i=500000; while(i--){
go(1,2,3,4,5,6,7,8);
}
However, if none (or a few) of those arguments ever change for this particular usage of the function, then it's far better to do this (from a speed pov - obviously not an asynchronous pov):
var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
go();
}
In order for the above to work you only need a slight modification to the original function:
var go = function (a,b,c,d,e,f,g,h, i) {
if ( go.args ) {
i = go.args;
a = i[0]; b = i[1];
c = i[2]; d = i[3];
e = i[4]; f = i[5];
g = i[6]; h = i[7];
}
return a+b+c+d+e+f+g+h;
}
This second function runs significantly faster because you are not passing in any arguments (a function called with no args is very quick to initiate). Pulling the values from the .args array doesn't seem to be that costly either (unless you involve strings). Even if you update one or two of the args it's still far faster, which makes it perfect for pixel or imagedata manipulations because you are normally only shifting x & y:
var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
go.args[2] = i;
go();
}
So in a way this is an example of where an object property can be faster than local vars - if a little convoluted and off topic ;)
Possible browser optimizations notwithstanding, accessing a property of an object is more expensive than accessing a local variable (but not necessarily a global variable or a variable of a parent function).
The deeper the property, the more of a performance hit you take. In other words,
for(var x=0; x<65536; x++)
doSomething(objArray[0].property1, objIDX=0);
would be improved by caching objArray[0].property1, and not repeatedly assigning to objIDX:
var prop = objArray[0].property1;
objIDX = 0;
for(var x=0; x<65536; x++)
doSomething(prop, 0);

Javascript Performance: Assign object fields at creation or later?

Does anyone know whether there are any performance trade-offs/advantages to assigning an object's fields at creation rather than later e.g.
var exObj = new exampleObject(name, date);
OR
var exObj = new exampleObject();
exObj.name = "blah";
exObj.date = "blah";
(assuming you've created your class accordingly)
Also, as a side thought, given that JS arrays are stored as objects, am I correct in assuming that there are no performance differences between using one over the other ? (For some reason using an array with a numeric index "feels" faster.)
Cheers
N
Test it yourself - http://jsperf.com/assign-object-fields-at-creation-or-later

Categories