17 Jan 2012

First element of an object in JavaScript

This one will go into the bag of clever hacks which you should use sparingly, if not ever. Given an object like this:

var obj = { a: "foo", b: "bar", c: "baz" }

Here’s how we get the “first” property of the object/dict:

for (var first in obj) break;
console.log("First property is: "+first);

We’re assuming here that the enumeration order matches the insertion order. Since ECMAScript standard itself does not specify any enumeration order, most browsers I have tested this in defaults to the insertion order. However, there is a catch: as explained in this discussion, if any of the property names can be parsed as an integer (e.g. 123), then V8 (Chrome’s JS engine) does not give any guarantee on the ordering of the keys.

There is lots of debate on that thread on the merits and demerits of preserving the order of insertion. Although, the V8 guys are pushing back on this on the basis of performance implications, Firefox 7.0 on my mac always preserves the order of insertion.

If you want to try it out on your browser, the following snippet

var a = {"foo":"bar", "3": "3", "2":"2", "1":"1"};
for(var i in a) { console.log(i) };

should print

foo
3
2
1

14 Jan 2012

Git bisect

You are part of a large team, and a bug has secretly crept into your codebase. You are on a mission to find out which exact commit caused that bug. I found myself on such a mission recently, and I thought I will write a quick post on how I used the awesome bisect command to identify the faulty commit quickly.

Let’s assume that the latest git commit id on your master branch is abcd. Let’s say that you do know that this bug did not exist in the previous release, whose last git commit id is wxyz. To identify the git commit which introduced this bug, and which lies between wxyz and abcd, do this:

$ git bisect start
$ git bisect good wxyz
$ git bisect bad abcd

You are essentially telling Git to bisect the commits between wxyz and abcd. Git will temporarily move you to a new branch called bisect and will now point to a commit that’s in the middle of both commits.

Bisecting: 34 revisions left to test after this
[25d71758dd0e131e9409f3896416eabc81d69ec8] Search field fixes

Verify whether the bug exists at this state. If it still does, type:

$ git bisect bad

Once again, Git will halve the number of commits needed to test by pointing you to a commit that’s right in the middle, between the previous bad commit and the good commit. Continue this process, telling git at each stage, whether a commit is “good” or “bad”, and git will eventually identify the first bad commit.

5bc592ab9065b12bf1bc516ab9e0fe461699971b is the first bad commit

Once you are done figuring out what changes caused the bug, you can return back to your original working state by:

$ git bisect reset

No responses

/
tagged with:

4 Jan 2012

Where I use HTML5 the most – admin interfaces

Both HTML5 and CSS3 have constantly evolving specs. With browser vendors going ahead and implementing new features using vendor prefixes, and long before they get accepted as part of the standard, we’re faced with a dilemma: We have all these cool toys which we can play with, but can’t really put them to use immediately in production because it’s going to take time for the rest of the world to upgrade their browsers.

What I have been doing lately is using admin interfaces as a ground for testing and learning about these new features. So long you get your clients to use the latest build of Firefox or Chrome, you are good to go. With Chrome, that’s pretty easy with the automatic rolling updates, and Firefox will soon be doing the same. Of course, this is not going to happen with every client, but it’s not that hard to make them use a better browser by just telling them how it can save them development cost. And, that’s true.

The other day, I had to get color alternating rows of a table – grey, white, grey, white, and so on. With an older browser, you have to resort to first modifying your code to give alternate rows class="odd" and then specifying a different color for this class in the CSS file. With CSS3, you can just do:

tr:nth-child(odd) { 
    background-color:#eee; 
}

Want to highlight only the first child of a parent?

#parent-id:nth-child(1) {
    background: #eee;
}

Quick form validation on an internal admin tool? HTML5 form validators FTW.

<input type="text" pattern="[-0-9]+" required />

Those are admittedly trivial examples, but the fact is knowing these little shortcuts quickly add up and help you get stuff done faster. As an added bonus, you also keep your presentation and code separated. The next time you look at a CSS3 or HTML5 feature and think that you can only use them in 2015, think again!

26 Dec 2011

ECMAScript harmony features in Chrome Canary

The latest Canary build of Google Chrome allows you to unlock some new features from ECMAScript Harmony. However, they are disabled by default, so to enable them you have to type about:flags into your address bar, and turn on “Enable Experimental JavaScript” which is found right at the bottom of the page.

Now, you have access to proxies, weak maps, maps, and sets!

Proxies

I am very excited about the Proxy API – it will allow you to create objects whose properties can be computed at run-time dynamically, and for hooking into other objects for auditing and logging purposes. A simple example:

var proxyObj = Proxy.create({
  get: function(obj, propertyName) {
    return 'Hello, '+ propertyName;
  }
});
 
console.log(proxyObj.John); // "Hello, John"

You can do all kinds of meta programming stuff using Proxies (that’s probably another blog post).

Maps and Weak Maps

The use of Maps and WeakMaps allows you to create dicts where the keys are objects.

var m = new Map();
var obj = {foo: "bar"};
m.set(obj, "baz");
m.get(obj);   // "baz"

The difference between a WeakMap and Map is that the WeakMap is not enumerable. Although the Map is enumerable, it relies on the iterator proposal, which is yet to be implemented in V8. So for all practical purposes, the Map and WeakMap are essentially the same for now.

Set

Again, you can add, delete and check for existence of a value in a Set, but cannot yet iterate through it.

var s = new Set();
s.add(2);
s.has(2); // true
s.had(10); // false

Finally, there was is a small but significant change in the way typeof operates on null. In ES3:

typeof null === 'object';  // true

But in ES5:

typeof null === 'null';  // true

This page from ECMAScript Harmony Wiki talks more about this semantic change, and how to support both ES5 and ES3 when writing code.

The immediate value of any of these features to browser-side JavaScript development is probably none, but nevertheless I’m excited to see the roll out of ES5 and ES6 features into V8, so we can start using them soon on atleast node.js.

You can follow me on Twitter right here.

7 Dec 2011

Abusing Scala’s anonymous argument

In Scala, you can use the underscore (_) to refer to an argument you are lazy to name.

val numbers = List(1,2,3,4)
numbers.map(2 * _)  // List(2, 4, 6, 8)

You can go a step further.

val numbers = List(1,2,3,4)
numbers.map(2*)

You can completely omit the _ as well, because * is actually a method on 2. Scala is smart enough to understand that it requires one parameter, and automatically passes it each element of the list.

In my last post on Scala, I mentioned how Scala’s power can be easily abused. This is one instance where it’s easy to end up abusing the convenience offered by the language. Let’s look at another code snippet:

// constant defined somewhere
val photoPath = "photos/"
 
// in another file
val memberIds = List("abc","def","ghi","jkl")
val photoUrls = memberIds.map("http://example.com/member/"+photoPath+)

See that innocuous looking + operator at the end of the last line? It’s very easy for someone who is tired at the end of a long day to just delete that, thinking that it’s a stray operator left behind by some lazy developer. Ouch.

Having said that, the use of anonymous arguments is elegant in some cases. Consider this:

def complicatedLogic(x:Int) = {
  // do something complicated
  x*2
}
val input = List(1,2,3,4)
val output = input.map(x => complicatedLogic(x))

We can rewrite that last line this way:

val output = input.map(complicatedLogic)

P.S: I have taken the liberty to use the term “anonymous argument” here to refer to this handy trick – but I will update the post if someone can tell me what this behavior is referred actually as.

You can follow me on Twitter right here.

No responses

/
tagged with: