Tuesday, January 19, 2016

JavaScript Function: Overloading

Many object-oriented programming language supports Function Overloading: defining multiple functions with the same name and return value but with different parameters/arguments.

Let's use Java as an example:
public void displayName(String firstName){...}
public void displayName(String firstName, String lastName){...}
public void displayName(String firstName, Formatter format){...}
public void displayName(String firstName, String lastName, Formatter format){...}
JavaScript does not support function overloading because the type of the function parameters are not known hence there are cases where the signature of the function cannot be differentiated.

Let's use the following (invalid) example to describe why JavaScript does not support function overloading:
// Function with 1 parameter
function displayName(firstName){...};

// Function with 2 parameters, both are string, so far so good,
// JS engine can differentiate them (technically no, but let's just pretend)...
function displayName(firstName, lastName){...};

// Function with 2 parameters, but the second one is a method (or object)...
// JS Engine will not be able to differentiate the difference between
// lastName and formatter as the second parameter while JVM runtime
// knows based on the type information:
// string for lastName and Formatter for formatter.
function displayName(firstName, formatter){...};
JavaScript engine will take the last function definition that exist in the code as the actual implementation, throwing out the previous function definition.

Even though JavaScript does not support function overloading, it doesn't mean JavaScript is unable to imitate the feature. This is when the Function arguments object shines.

The above Java implementation can be simplified to:
function displayName(firstName, lastName, customFormatter){
  if(arguments.length === 0){
    console.log("No parameter passed");
  }

  // Formatter is always the last one.
  var formatter;
  if(typeof arguments[arguments.length-1] === 'object'){
    formatter = arguments[arguments.length-1];
  }else{
    // let's assume DefaultFormatter exist.
    formatter = new DefaultFormatter();
  }

  var display = '';
  if(lastName && typeof lastName === 'string'){
    display = formatter.format("%s %s", firstName, lastName);    
  }else{
    display = formatter.format("%s", firstName);
  }

  console.log(display);
}

// only display first name using default formatter
displayName("John"); 

// only display first name with custom formatter
// imagine if the display follows Arabic: starts from Right to the Left
// instead of Left to Right like Roman...
displayName("John", new RightToLeftFormatter());

// display first and last name using default formatter
displayName("John", "Doe");

// display first and last name using VerticalFormatter
// imagine if the name is displayed vertically instead of horizontal ;)
displayName("John", "Doe", new VerticalFormatter());
From the above example, it appears that the JavaScript solution to imitate Function Overloading looks simpler compare to Java.

No comments:

Post a Comment