Dating JavaScript: Getting to Know Functions

I’ve been dabbling with JavaScript for a while now but still don’t have a solid grasp of the language. In an attempt to level up and start writing better JS I plan to write posts about fundamental JavaScript concepts starting with Functions.

The style of these posts will be more like detailed notes than blog posts. Thus they probably won’t be helpful if you don’t know anything about JavaScript. If that’s the case I recommend starting with Codecademy’s JS Track.

Finally, before I dive into the basics of functions I need to give credit where credit is due. For these posts, I’ll be perpending the title with “Dating JavaScript”. Recently my coworker and mentor, Damon Aw, did a short JS training, with the same name. I think it’s a great way to describe learning a new language, especially one as quirky as JavaScript and so… I’m stealing it.

Why Start With Functions

Functions are an extremely important and powerful part of the language, or as Douglas Crawford puts it in his book, JavaScript: The Good Parts, “Functions are the fundamental modular unit in JavaScript. They are used for code reuse, information hiding, and composition.”

Or in the words of Nicholas C. Zakas in his book, The Principles of Object-Oriented JavaScript, “You need a good grasp of functions to understand how object- oriented programming works in JavaScript. Because JavaScript has no concept of a class, functions and other objects are all you have to work with to achieve aggregation and inheritance.”

Functions are Objects

The first thing you need to be aware of is that functions are objects in Javascript and thus can be used like any other object in the language. Meaning you can:

  • Assign them to variables
  • Add them to objects as properties
  • Pass them to functions
  • Return them from functions

Anatomy of JavaScript Functions

JS Function Anatomy

  1. Function Keyword - this simply let’s you know the object is a function.
  2. Function Name - a function name is optional. If a function does not have a name, as is the case when using function expressions (see below), it’s called an anonymous function. Function names can also be used by the function to call itself recursively and are used by debuggers and dev tools to ID the function.
  3. Function Parameters - parameters appear in between parenthesis and are separated by commas. Once inside the function the parameters are stored as variables.
  4. Function Statement - a set of statements that make up the body of the function.

Two Forms of JavaScript Functions

There are two forms of function literals that are very similar but differ in small but important ways.

1. Function Declarations - Function keyword followed by the name

1
2
3
4
5
function sayFullName(firstName, lastName) {
  console.log(fisrstName + " " + lastName);
}

sayFullName("Kyle", "Doherty"); // Kyle Doherty

Note: function declarations are hoisted to the top of the context, meaning it doesn’t matter when the function is defined because the program knows about it as soon as it’s ran. Read more about hoisting here or watch the video below.

2. Function Expressions - sets the function to a variable and are not hoisted.

1
2
3
4
5
var multiplication = function(x,y) {
    x * y
};

multiplication(10, 5); // 50

Parameters

Functions don’t care how many parameters are passed to them. This means they won’t throw an error regardless of how many params are sent. However, while they don’t care they do know how many params they’re “able” to take through their length property.

1
2
3
4
5
6
7
function oneArg(x) {
  console.log(x);
}

console.log(oneArg.length); // 1
console.log(oneArg("Hi")); // Hi
console.log(oneArg("Hola", "a second params", "and a third")); // Hola

Above you can see length returns 1 because this function only takes a single param. Yet, if you pass in additional params no error occurs and the function simply ignores the extras.

How Params are Stored

The names of the params are stored as variables inside the function. In addition to the parameters passed into the function it has two bonus parameters: this and arguments. This is beyond the scope of this post so don’t worry about it now. Arguments is an array like structure that contains all the parameters passed into the function. Just like an array it can store any number of values that are referenced by indices (0, 1, 2, etc.), and has a length property stating how many values are present.

1
2
3
4
5
6
function noArgs() {
   console.log(arguments[0]);
}

console.log(noArgs.length);  // 0
noArgs("hi");  // hi

In this example the function takes no params, but can still access any parameters passed into it through its arguments object. Here it’s accessing the first parameter in the arguments object in the same way you’d get the first element in an array.

This is sort of weird/confusing and thus generally not done. Normally you’d have a set number of params the function expects and only use those.

Sometimes It’s a Good Thing

However, the ability to take any number of arguments can prove useful at times.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function sum() {

  var result = 0,
      i = 0,
      length = arguments.length
      // number of parameters sent in to the function

  while (i < length) {
    result += arguments[i];
    i++;
  }

  return result;
}


console.log( sum()); // 0
console.log( sum(2, 2)); // 4
console.log( sum(3, 10, 10, 2)); // 25
console.log( sum(50)); // 50

Using the arguments object and a while loop the function is able to sum all the parameters given to it regardless of how many are sent it.

Function Overloading

Function overloading is a concept in some OO languages where you can create two functions with the same name but different implementations. The program would then choose which one to use based on the number of params that were sent to the function.

Since functions can accept any number of params you can’t do this. If you define two methods with the same name the one that was defined last effectively overwrites the first one you defined.

1
2
3
4
5
6
7
8
9
function sayHi() {
  console.log("Hi");
}

function sayHi() {
  console.log("Hello!");
}

sayHi();  // Hello!

Here you can see the second sayHi function overwrote the first one.

The way to mimic function overloading is to use conditionals to react differently depending on what params are sent to the function.

1
2
3
4
5
6
7
8
9
function saySomething(stuff) {
  if (stuff === undefined) {
    console.log("You didn't say anything!");
  } else {
    console.log(stuff);
  }
}

saySomething(); // You didn't say anything!

Recommended Resources

Copyright © 2015 - Kyle Doherty. Powered by Octopress