Well, I read a lot of stuff regarding this topic and I saw people being very controversial about it. Before reaching my clearer conviction about whether it's by reference or value, I was minded to accept the following statements:

"Primitive type variables like strings and numbers are always passed by value.
Arrays and Objects are passed by reference or by value based on these conditions:

  • if you are setting the value of an object or array it is Pass by Value.

object1 = {prop: 'car'};
array1 = [1,2,3];

  • if you are changing a property value of an object or array then it is Pass by Reference.

object1.prop = 'car';
array1[0] = 9;"

Although these statements do reflect how JS functions seem to handle parameters, I wasn't really convinced with it. But then I saw this post, with nice pretty drawings, and I came to understand that variables are POINTERS to something (whether it's an object, array, primitive type, whatever). This is, actually, the key point for this matter (since parameters are nothing more than variables declared within the context/scope of a function). Let's use illustrations to visualize how JS handles variables assignments (let's not worry about scopes so we can focus on one thing only).

Consider the instruction:

var motorcycle = "Honda Shadow";

When I assign something to my motorcycle-named variable, JS makes that variable point toward it (an immutable string "Honda Shadow").

When we re-assign something to the motorcycle variable, JS simply makes that variable point toward our new thing (in this case, an object). "Honda Shadow" string will be picked up and taken care of by the JS Garbage Collector. 

motorcycle = {
	manufacturer: "Honda",
	model: "Shadow"
}

 

And the same would happen to the properties of my object, because objects are just variables containing variables:

motorcycle.model = "CBR";

 

Only to reinforce, if we assign a new object to it:

motorcycle = {
	manufacturer: "Yamaha",
	model: "R1"
};

 

 

Okay, now, what happens when we pass the variable motorcycle as a parameter in a function? Well, now we have two variables (one declared in the global scope, motorcycle, and the other declared within the function scope), pointing towards the same thing (our Yamaha R1).

var motorcycle = {
	manufacturer: "Yamaha",
	model: "R1"
}

function whatever(arg)
{
	//arg equals {manufacturer: "Yamaha", model: "R1"}
}

whatever(motorcycle);

 

If we change the object's model property within the function, we end up affecting "both" objects since they reference the same thing. 

var motorcycle = {
	manufacturer: "Yamaha",
	model: "R1"
}

function whatever(arg)
{
	arg.model = "XT";
}

whatever(motorcycle);
//motorcycle equals {manufacturer: "Yamaha", model: "XT"}

 

Now comes the break-through part! If we assign a new object to the arg variable within the function scope, we'll make it point towards another thing, as we've seen several time above, but that doesn't change the fact that the outer (or global) variable motorcycle is still pointing to the old thing!

var motorcycle = {
	manufacturer: "Yamaha",
	model: "XT"
}

function whatever(arg)
{
	arg = {
		manufacturer: "Kawasaki",
		model: "Ninja"
	};
}

whatever(motorcycle);
//motorcycle equals {manufacturer: "Yamaha", model: "R1"}

 

Capiche?

Check out this live demo.