Thursday, May 8, 2014

By value or reference?

In JavaScript writing functions is easy. No need to declare return type, no need for argument types, In fact you don't even need to declare arguments! One might argue if all this freedom is actually a good thing. Freedom or not, it is important to understand the JS very basics and understand if what we pass into functions is passed by value or reference.

If you are familiar with Java the behaviour in JS will make sense to you. For all those confused however about how arguments are passed into functions I put together quick example that I hope is self explanatory. Consider the code:

var a = 100,
    b = "Homer",
    c = {
        firstName: "Homer"
    },
    d = {
        firstName: "Homer"
    },
    e = {
        firstName: "Homer"
    },
    f = {
        firstName: "Homer"
    }

function changeName(a1, a2, a3, a4, a5, a6) {
    a1 = 200;
    a2 = "Bart";
    a3.firstName = "Bart";
    a4 = {
        firstName: "Bart"
    };
    delete a5.firstName;
    delete a6;
}

changeName(a, b, c, d, e, f);
// output
console.log("a1:"+a); // 100
console.log("a2:"+b); // Homer
console.log("a3:"+c.firstName); // Bart
console.log("a4:"+d.firstName); // Homer
console.log("a5:"+e.firstName); // undefined
console.log("a6:"+f); // object


Ok, a and b are primitive types and these are obviously passed by value. References to objects are also passed by value. Confused? Let me explain..

Lets start with c, its a3 inside of function. Its an objects reference passed into a function. Inside we modify its property and it does modify original object c that a3 references.

Now da4 argument inside the function. Again reference to object with firstName property "Homer" is passed (by value) into a function as a4 argument. Inside the function we assign other object to a4 argument. From now on a4 is a reference to different object. Modify it all you want, d from outside won't be touched.

e and f are straightforward really. In case of a5 reference to firstName is deleted and in case of a6 the a6 reference pointing to original object is deleted. Original object stays however and can be accessed by still existing reference f from outside of function.

Understanding of all this is pretty fundamental I believe and getting it wrong might result in bugs and confusion. Luckily for us all its also fairly easy concept to grasp and as easy to experiment with.

Wednesday, May 7, 2014

jQuery and Array-like objects in JavaScript

JavaScript with its closures, prototypal inheritance etc. is not the easiest language to learn. Knowing certain topics is very important in effective writing and debugging JS code. I believe that Array-like objects is one of those concepts that everyone should get familiar with. Where can we find such thing? arguments accessible inside of functions is one example. jQuery returns such animal when you call $(“someSelector”). It looks like Array, behaves (in some cases) like Array, but its not Array. Try:

var a={},b=$(“div”), c=[],d=new Array();

a instanceof Array // outputs false (duh..)
b instanceof Array // outputs false
c instanceof Array // outputs true
d instanceof Array // outputs true


c and d are arrays, a and b not so much though. a is self explanatory, its an object literal. b is Array-like object jQuery returns.

As a is furthest from what Array should look like lets try to make it closer to what arrays are. Start from beginning and attach few properties to it e.g.:

a={ 1:”first”, 2:”second”};

Now calling (e.g. in Chrome dev tools):

a

Will output:

Object {1: "first", 2: "second"}

And calling:

a[1] // outputs first

a[2] // outputs second


However:

a.length

Outputs:

undefined

And for a good reason. It is still plain object and length property doesn't exists. Ok, so lets fake it till we make it and lets add:

a.length=2;

Now calling a from console will output:

Object {1: "first", 2: "second", length: 2}

True Arrays also have number of methods so lets add some and see what happens:

a.push=function() {}

Outputs:

Object {1: "first", 2: "second", length: 2, push: function}

Not much change. The trick lies in splice method. Simply add:

a.splice=function() {}

and voila! Calling a will output:

[undefined × 1, "first"]

Now, look at our original object. Its missing “0” element hence undefined in output above. Also “second” is missing as our length was set to 2 only.

Now, can we make it even more Array-like? Sure we can! Our splice and push implementations are empty so lets fill one in, e.g.:

a.push=function(el) {
// here you can extend implementation or not, then we call Arrays push
Array.prototype.push.call(this,el);
}


Now try:

a.push(“third”);

And call:

a

Result will be:

[undefined × 1, "first", "third"]

Calling a.length will return:

3

So third element was added to our fake array. Even length property increased by one. Hows that for array? :)

All good. We got ourselves Array-Like object. a instanceof Array will still return false, but its close.

As you see jQuery isn't using any sort of black magic, and I hope this gives you better understanding of Array-like objects that you often see in JavaScript. This is only the beginning however and if you are brave and want to learn more there is no better way then try it for yourself e.g. play around with a.__proto__=[].__proto__ and var b={};b.__proto__.{}.__proto__ and such. Or try removing splice from jQuery Array-like object or .. ok I better stop now but TRY, all these are fun too!