carr3r

Do Javascript functions pass parameters by reference or value?

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.

Method overloading and overriding in PHP

I recently got asked (in an interview) if PHP supports method overloading and overriding. Without properly processing the question, I luckily gave a doubtful "yes" for an answer. The interviewer,  thank goodness, didn't require further details. At that moment, it wasn't really clear to me how PHP accomplishes these two forms of polymorphism. Be careful: in PHP, they are tricky!, specially Method overloading.

Let's remind what method overloading & overriding are (and let's use Java for comparison): 

  • Method overloading is when you define the same method name twice (or more), within the same class, using different set of parameters.
    public class Calculator
    {
    	protected double memory = 0;
    	
    	public void Add(int number)
    	{
    		memory += number;
    	}
    
    	public void Add(double number)
    	{
    		memory += number;
    	}
    
    	public void Add(int number1, int number2)
    	{
    		memory += number1 + number2;
    	}
    
    }
  • Method overriding is when you extend a class and rewrite a method (with the same set of parameters) defined in the parent class.
    public class CalculatorPercentage extends Calculator {
    
    	public void Add(int number)
    	{
    		memory += (memory*number/100);
    	}
    
    	public void Add(double number)
    	{
    		memory += (memory*number/100);
    	}
    
    	public void Add(int number1, int number2)
    	{
    		memory += (memory*number1/100) + (memory*number2/100);
    	}
    
    }

Now let's try to translate the Calculator class to PHP, in a very very naive way.

class Calculator
{
	protected $memory = 0;
	
	public function Add(int $number)
	{
		$this->memory += $number;
	}

	public function Add(double $number)
	{
		$this->memory += $number;
	}

	public function Add(int $number1, int $number2)
	{
		$this->memory += $number1 + $number2;
	}

}

If we try to run it, PHP will throw a fatal error:

PHP Fatal error: Cannot redeclare Calculator::Add()

That's because PHP actually doesn't fully support method overriding but it provides you two ways of achieving it: using Magic Methods and Variable-length argument lists

Magic method

__call(string $name , array $arguments) is a magic function that will be called whenever you request a method that hasn't been declared within your class (neither within its parents). Also, Type Hinting doesn't work with scalar types in PHP5.

Adjusting our previous naive-attempt code, we would have:

class Calculator
{
	protected $memory = 0;
	
	public function __call($method_name, $parameters)
	{
		if ($method_name == "Add")
		{
			switch (sizeof($parameters))
			{
				case 1:
					$this->memory += $parameters[0];
				break;
				case 2:
					$this->memory += $parameters[0] + $parameters[1];
				break;
			}
		}
	}
}

... and its child class CalculatorPercentage:

class CalculatorPercentage extends Calculator
{
    	public function __call($method_name, $parameters)
	{
        	if ($method_name == "Add")
	        {
        	    switch (sizeof($parameters))
	            {
        	        case 1:
                	    $this->memory += ( $this->memory * $parameters[0] / 100 );
	                break;
        	        case 2:
                	    $this->memory += ( $this->memory * $parameters[0] / 100 ) + ( $this->memory * $parameters[1] / 100 );
	                break;
	            }
        	}
	}    
}

Variable-length argument lists

In PHP versions lower than 5.5, we can completely omit the parameters signature part in the method declaration and still recover that information using func_num_args() and  func_get_args() within its body to decide which behavior the method should take to a given set of parameters. 

For instance,

function example()
{
	echo "You've called me passing ". func_num_args()." arguments.\n";
	if ( func_num_args() )
		print_r( func_get_args() );
}

example();
example('Hello world');
example(array('1',2), '3', new stdClass());

would output:

You've called me passing 0 arguments.
You've called me passing 1 arguments.
Array
(
    [0] => Hello world
)
You've called me passing 3 arguments.
Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
        )

    [1] => 3
    [2] => stdClass Object
        (
        )

)

In PHP versions greater than 5.6, we can use ... on the method's signature to indicate that method will receive a variable-length list of parameters. Making use of this resource, our Calculator class can be written as follows:

class Calculator
{
	protected $memory = 0;
	
	public function Add(...$parameters)
	{
		foreach($parameters as $number)
			$this->memory += $number;
	}
}
Home ← Older posts