Saturday, 26 October 2013

Javascript Fundamentals Part 1

This is the first in a series of posts aimed at understanding the fundamentals of JavaScript which I will place here. The source code for this series of blog posts can be found here

Passing parameters to functions

Is it by reference or by value?

Whether a parameter is passed to a function by value or by reference is the question most natural to programmers from other languages. To answer this question consider that all primitives (undefined, null, boolean, numbers and strings) are immutable whereas objects are mutable. So from the latter it would seem primitives are passed by value and objects by reference. Lets see.

Passing objects around

So let's look at the following code example.
 function loadEmployees() {
        var employees = EmployeeService.getEmployees();
        if (!employees 
           || !Array.isArray(employees)
           || employees.length <= 0) return employees;
       
       var index = 0;
       for(index in employees) {
            var employee = employees[index];
            formatEmployeeDisplayText(employee) ;
       }
       return employees;
    }
    
    function formatEmployeeDisplayText(employee) {
        if (!employee
            || !employee instanceof jsFundementals.staff.Employee ) {
            throw new Error("Record presented is not an instance of jsFundementals.staff.Employee");
        }
        employee.displayText = (employee.title || " ") +  " " +
                                            (employee.firstName || " [first name]") +  " " +
                                            (employee.lastName || " [lastname]");
    }
Each employee record is passed to the formatEmployeeDisplayText function and it's displayText property is set. Objects are mutable so the displayText property remains set after returning from the formatting function.

Passing primitives around

The following code passes a string to a function expecting any changes to it to persist when that function returns:
/*
This will not work because strings are immutable.
*/
function() {
 var warnings = "";
 var employees = loadEmployees(warnings);
 if (warnings) {
   console.log(warnings); //This will never execute.
 }
 return employees;
}

function loadEmployees(warnings) {
         var employees =[];
        try {
        employees = EmployeeService.getEmployees();
        if (!employees
                || !Array.isArray(employees)
                || employees.length <= 0)
            return employees;

        var index = 0;
        for (index in employees) {
            var employee = employees[index];
            formatEmployeeDisplayText(employee);
        }
        } catch(e) {
            warnings += e.message  + " was encountered during employee loading.";
        }
        return employees;
    }
This kind of mistake is easy to make. The warning may be set in the function but does not persist when it returns.

Can we set an object to a new instance?

So, if we pass in a parameter that is an instance of an object can the function change it to point to a new object instance.
 //...
if (!nextEmployee || !nextEmployee.displayText) {
                               nextEmployee = new jsFundementals.staff.Employee();
                               makeDefaultEmployee(nextEmployee);//Will not alter the nextEmployee.
}
//...
/*
Does not work because you can not change the object the value points to.
*/
function makeDefaultEmployee(employee) {
 employee = new jsFundementals.staff.Employee("[title]", "[firstName]", "[lastName]");
}
This is what one would expect. Objects are mutable but parameter values can not be changed to point to new object instances.

No comments:

Post a Comment