Friday, October 4, 2013

Collections, Objects and Arrays in JavaScript


- how to loop through a collection of objects and their properties
- how to check whether an object is null or undefined
- how to find a particular object with a search in a collection or an array
- and so on…
It leads me to think of how many type of type of collections or objects or array in available in JavaScript. In Objective-C, we have NSObject, NSArray, NSMutableArray, and others. As it turns out, in JavaScript, we have only majorly three types. Which are namely Collections/Objects and Arrays. Simple, right? As I dig further, some nice folks at stackoverflow has made a tremendously helpful answer that might as well be a standalone tutorial of these types.
While you are at it. Don’t forget to check out the performance testcase here.
Literals
The [] and {} are called the array and object literals respectively.
var x = [] is short for var x = new Array();
and var y = {} is short for var y = new Object();
Arrays
Arrays are structures with a length property. You can access values via their numeric index.
var x = [] or var x = new Array();
x[0] = 'b';
x[1] = 'c';
And if you want to list all the properties you do:
for(var i = 0; i < x.length; i++)
console.log(x[i]);// numeric index based access.
Performance tricks and gotchas
1. Inner-caching the length property
The standard array iteration:
for (var i = 0; i < arr.length; i++) {
    // do stuff
};
Little known fact: In the above scenario, the arr.length property is read at every step of the for loop. Just like any function you call there:
for (var i = 0; i < getStopIndex(); i++) {
     // do stuff
};
This decreases performance for no reason. Inner caching to the rescue:
for (var i = 0, len = arr.length; i < len; i++) {
     // enter code here
};
Here’s proof of the above.
2. Don’t specify the Array length in the constructor.
// doing this:
var a = new Array(100);
// is very pointless in JS. It will result in an array with 100 undefined values.

// not even this:
var a = new Array();
// is the best way.

var a = [];
// using the array literal is the fastest and easiest way to do things.
Test cases for array definition are available here.
3. Avoid using Array.prototype.push(arr.push)
If you are dealing with large collections, direct assignment is faster than using theArray.prototype.push(); method.
myArray[i] = 0; is faster than myArray.push(0);, according to jsPerf.com test cases.
4. It is wrong to use arrays for associative assignments.
The only reason why it works is because Array extends the Object class inside the core of the JS language. You can just as well use a Date(); or RegEx(); object for instance. It won’t make a difference. x['property'] = someValue MUST always be used with Objects.
Arrays should only have numeric indexes. SEE THIS, the Google JS development guidelines! Avoid for (x in arr) loops or arr['key'] = 5;.
This can be easily backed up:
var x = [];
console.log(x.prototype.toString.call);
will output: [object Array]
This reveals the core language’s ‘class’ inheritance pattern.
var s = new String();
console.log(x.prototype.toString.call);
will output [object String].
5. Getting the minimum and maximum from an array.
A little known, but really powerful trick:
function arrayMax(arr) {
    return Math.max.apply(Math, arr);
};
, respectively:
function arrayMin(arr) {
    return Math.min.apply(Math, arr);
};
Objects
With an object you can only do:
var y = {} or var y = new Object();
y['first'] = 'firstValue' is the same as y.firstValue = 'firstValue', which you can’t do with an array. Objects are designed for associative access with String keys.
And the iteration is something like this:
for (var property in y) {
    if (y.hasOwnProperty(property)) {
        console.log(y.property);
    };
};
Performance tricks and gotchas
1. Checking if an object has a property.
Most people use Object.prototype.hasOwnProperty. Unfortunately that often gives erroneous results leading to unexpected bugs.
Here’s a good way to do it:
function containsKey(obj, key) {
    return typeof obj[key] !== 'undefined';
};
2. Replacing switch statements.
One of the simple but efficient JS tricks is switch replacement.
switch (someVar) {
    case 'a':
        doSomething();
        break;
    case 'b':
        doSomethingElse();
        break;
    default:
        doMagic();
        break;
};
In most JS engines the above is painfully slow. When you are looking at three possible outcomes, it doesn’t make a difference, but what if you had tens or hundreds?
The above can easily be replaced with an object. Don’t add the trailing (), this is not executing the functions, but simply storing references to them:
var cases = {
    'a': doSomething,
    'b': doSomethingElse,
    'c': doMagic
};
Instead of the switch:
var x = ???;
if (containsKey(cases, x)) {
    c(x);
} else {
    console.log("I don't know what to do!");
};
3. Deep-cloning made easy.
function deepClone(obj) {
   return JSON.parse(JSON.stringify(obj));
};

function fastDeepClone(obj) {
   var tmp = {};
   for (var key in obj) {
       tmp[key] = obj[key];
   };
};
- See more at: http://blog.shoguniphicus.com/2013/08/13/js-collections-objects-and-arrays-in-javascript/#sthash.UdH8n45L.dpuf

0 comments:

Post a Comment