In Studio: Javascript Primitives
[tweetmeme source=”anismiles” only_single=false http://www.URL.com%5D
Javascript – and for that matter most other languages – has two kinds of stuffs: primitives and objects. Primitives are immutable and stored in a variable entirely. That is, when you do assignments among primitives, the assigned receives a copy from the assigner.
y = x; // y receives a copy of x.
Objects are not stored in the variable. They stay somewhere else, and the variable only holds a reference to that location. So, in case of object assignments only references get copied.
obj2 = obj1; // obj2 receives a copy of reference to the object referred by obj1.
That is, both obj1 and obj2 now points to the same object, and if you change this object – the change will be observed by both obj1 and obj2.
In Javascript, there are 5 kinds of primitives: undefined, null, boolean, string and number. So, string “abc”, number 1, 1.34, boolean true, false – these all are primitives. Rest everything are Objects.
I know what you are thinking? Primitives are not Objects, and so they must not be able to execute any method on themselves – because they don’t have any – then how come this works?
console.log(“abc”.length); // prints 3
Well, the reason this works is that Javascript wraps these primitives with their Object counterparts.
“abc” ==> new String(“abc”)
true ==> new Boolean(true)
1 ==> new Number(1)
Recall Java’s wrapper objects? Well, this is almost the same and with more juicy auto-boxing in play. Javascript automatically coerces between primitives and Objects. In this case,
- string value is coerced into a String Object,
- property ‘length’ is accessed, and then
- the coerced Object is discarded for garbage collection!
Now, the hacker in you must have started thinking: If Javascript automatically coerces primitives to Objects; then certainly, you should be able to assign properties to a primitive too, like this:
var my_bank_account = “State Bank of India”; my_bank_account.city = “Indore”; console.log(my_bank_account.city); // prints undefined.
Oops. It failed. But why?
Well, what you guessed was right. The moment you tried to assign a property to the primitive, Javascript did indeed coerce primitive string into the wrapper Object – in this case, String. This new Object got itself assigned a brand new property – ‘city’ – too. But, since there wasn’t any placeholder to store the reference to this new Object, it was quickly discarded and sent for garbage collection. And when you went back to access the property ‘city’, Javascript again coerced your primitive to the wrapper Object – which incidentally is a new Object and doesn’t know anything about your ‘city’ property hence you see ‘undefined’.
Let me show you – roughly – what happens behind the scene:
var my_bank_account = “State Bank of India”; my_bank_account.city = “Indore”; ==> (new String(“State Bank of India”)).city = “Indore”; console.log(my_bank_account.city); ==> console.log( (new String(“State Bank of India”)).city );
This whole game seems messy? No. How do I know when am I dealing with primitives and when with Objects?
Well, you use ‘typeof’ operator.
typeof false; // ‘boolean’ typeof new Boolean(false); // ‘object’ typeof “Animesh”;// ‘string’ typeof new String(“Animesh”); // ‘object’ typeof 1.45; // ‘number’ typeof new Number(1.45); // ‘object’
Enlightened? Good. 🙂
One more thing: this entire coercion business is a double-way traffic. The way Javascript turns your primitives into Objects when needed, it can turn Objects into primitives too when required.
var s = new String(‘hello’); typeof s; // ‘object’ var p = s.valueOf(); // converts to primitive typeof p; // ‘string’
Javascript will automatically use ‘valueOf’ (and sometimes, ‘toString’) method whenever such a need arises. Watch this:
var x = new String(“abc”); typeof x; // ‘object’ var y = x + 1; // automatically calls valueOf() on Object x. typeof y; // ‘string’
Normally, you don’t need to worry about this thing. But knowing what goes on certainly helps at times. Don’t you think? Follow this:
var b = new Boolean(false); typeof b; // ‘object’ if (b){ console.log(“b is true.”); // Ah! When did b become true? }
What’s wrong with the above code? You must have thought that Javascript would coerce the Boolean object into primitive while evaluating ‘if’? Well, Javascript didn’t think so. It just went ahead and evaluated the Object directly for the condition… and since that Object was neither null nor undefined, it evaluated to true.
If you had done this:
if (b.valueOf(){ console.log(“b is true”); } else { console.log(“b is false”); // thank God! }
It would have come out differently. Remember this: unless there is a dire need, Javascript doesn’t perform any coercion.
I hope this article was helpful. I’ll be writing more on Javascript internals.
I have just started using Javascript. Very nice explanation of fundamentals. It makes things clear.Thanks
Sanjeev Kumar Dangi (@skdangi)
November 13, 2011 at 8:54 pm
Good one.
Ajay Rathore
July 23, 2012 at 5:36 pm