- 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 forvar x = new Array();
andvar y = {}
is short forvar y = new Object();
Arrays
Arrays are structures with a length property. You can access values via their numeric index.
And if you want to list all the properties you do:var x = [] or var x = new Array(); x[0] = 'b'; x[1] = 'c';
Performance tricks and gotchasfor(var i = 0; i < x.length; i++) console.log(x[i]);// numeric index based access.
1. Inner-caching the length property
The standard array iteration:
Little known fact: In the above scenario, thefor (var i = 0; i < arr.length; i++) { // do stuff };
arr.length
property is read at every step of the for loop. Just like any function you call there:
This decreases performance for no reason. Inner caching to the rescue:for (var i = 0; i < getStopIndex(); i++) { // do stuff };
Here’s proof of the above.for (var i = 0, len = arr.length; i < len; i++) { // enter code here };
2. Don’t specify the Array length in the constructor.
Test cases for array definition are available here.// 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.
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 thanmyArray.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 becauseArray
extends theObject
class inside the core of the JS language. You can just as well use aDate();
orRegEx();
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! Avoidfor (x in arr)
loops orarr['key'] = 5;
.
This can be easily backed up:
will output:var x = []; console.log(x.prototype.toString.call);
[object Array]
This reveals the core language’s ‘class’ inheritance pattern.
will outputvar s = new String(); console.log(x.prototype.toString.call);
[object String]
.
5. Getting the minimum and maximum from an array.
A little known, but really powerful trick:
, respectively:function arrayMax(arr) { return Math.max.apply(Math, arr); };
Objectsfunction arrayMin(arr) { return Math.min.apply(Math, arr); };
With an object you can only do:
var y = {}
orvar y = new Object();
y['first'] = 'firstValue'
is the same asy.firstValue = 'firstValue'
, which you can’t do with an array. Objects are designed for associative access withString
keys.
And the iteration is something like this:
Performance tricks and gotchasfor (var property in y) { if (y.hasOwnProperty(property)) { console.log(y.property); }; };
1. Checking if an object has a property.
Most people useObject.prototype.hasOwnProperty
. Unfortunately that often gives erroneous results leading to unexpected bugs.
Here’s a good way to do it:
2. Replacing switch statements.function containsKey(obj, key) { return typeof obj[key] !== 'undefined'; };
One of the simple but efficient JS tricks isswitch
replacement.
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?switch (someVar) { case 'a': doSomething(); break; case 'b': doSomethingElse(); break; default: doMagic(); break; };
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:
Instead of thevar cases = { 'a': doSomething, 'b': doSomethingElse, 'c': doMagic };
switch
:
3. Deep-cloning made easy.var x = ???; if (containsKey(cases, x)) { c(x); } else { console.log("I don't know what to do!"); };
function deepClone(obj) { return JSON.parse(JSON.stringify(obj)); }; function fastDeepClone(obj) { var tmp = {}; for (var key in obj) { tmp[key] = obj[key]; }; };
0 comments:
Post a Comment