Skip to content
jfraboni edited this page Dec 22, 2014 · 11 revisions

You should understand [Variables](Variables & Constants)

A function is any amount of code that is grouped together. You can use a variable to reference that code and in the future run it just by "invoking" that variable.

Syntax

// This is a function that will print out hi to the console
var sayHi = function() {
    console.log("Hi there everyone");
}

// You can invoke it like this (there are several other ways to invoke it too)
sayHi();

// you can pass parameters into a function and it can be as many lines as you want (though fewer is better)
var sayHiInformally = function(firstName) {
    var message = "Whats up " + firstName + " we're both cool.";
    console.log(message);
}

// You can invoke functions from inside other functions and functions can return values!
var getSalutation = function(firstName) {
    if(firstName == "David") {
        return "Mr.";
    }
    if(firstName == "John") {
        return "Mr.";
    }
    return "Mrs."; //Otherwise return Mrs
}
var sayHiFormally = function(firstName) {
    var message = "Greetings " + getSalutation(firstName) + " " + firstName;
    console.log(message);
}

sayHiFormally("John");    //will print "Greetings Mr. John"
sayHiFormally("Johanna"); //will print "Greetings Mrs. Johanna"

// A function declared this way (named function) will be visible everywhere in its scope
function superFormalHi(firstName) {
    console.log("Pleasure to meet you " + getSalutation(firstName) + " " + firstName);
}
// This can be invoked like normal
superFormalHi("Donna");

Why Functions?

Suppose you have some code for driving the car to the store

car.turnOnEngine();
car.driveForward();

if(stoplight1.isRed) {
    car.stop();
    car.waitForGreen(stoplight1);
    car.driveForward();
}

car.turnLeft();
car.driveForward();

if(stoplight2.isRed) {
    car.stop();
    car.waitForGreen(stoplight2);
    car.driveForward();
}

// ...

Notice what happens every time you hit a stoplight - you have to check if it's read, and if so stop and wait for green before continuing. And we have to do that at every single stoplight! What if there's ten stoplights on the way to the store? We can copy this code ten times of course. What if we later want to cautiously stop when the stoplight is yellow as well? Then we have to remember to change every...single...one.

So we write a quick function so that all of that code is in one place and easy to change in the future.

var handleStoplight = function(stoplight) {
    if(stoplight.isRed) {
        car.stop();
        car.waitForGreen(stoplight2);
        car.driveForward();
    }
}

we can now use it over and over again handleStoplight(stoplight1);, handleStoplight(stoplight2);, etc.`

This concept is incredibly important to oganizing code. In fact, it turns out that functions are quite possible the most important concept in javascript. Just like simple atoms combine to make the complex objects around us, it turns out simple functions can be combined to make fantastically sophisticated programming structures.

But first let's talk about some of the aspects of functions.

Function Scope

Consider the following code

var greeting = "What's Up";

var sayHi = function() {
    var greeting = "Hi";
    console.log(greeting);
}

sayHi();
console.log(greeting);

As you might intuitively suspect, this will print

Hi
What's Up

This is because variables created inside of a function exist only inside of that function. This is called function scope and is one of the most important concepts in javascript. It also means that you get results like this

Runnable Function Scope Example

var doStuff = function(){
    var informal = "Hi";

    var sayHi = function() {
        var formal = "Hello";
        console.log(informal); // prints "Hi"
    }

    sayHi();
    console.log(informal);// prints "Hi"
    console.log(formal); // ReferenceError - formal does not exist
}
doStuff();

Again, this should make intuitive sense. Inside of sayHi we can refer to the informal variable because both informal and the body of sayHi are inside the doStuff function. However, since the formal variable is inside of sayHi and the console.log(formal) line is not, we get an error.

When in doubt, just look up through the levels of indentation. If you want to know if a variable is visible to a particular line of code, tilt your head to the left and imagine the code is a landscape. Can you get from that line to the variable without climbing downhill?

Rotate code and picture as landscape

Consider the usage of the informal variable on line 6 above. Where is the declaration of informal that this relates to? Well start at line 6 and start climbing in both directions, never move downhill - jump over any canyons. The first var informal you encounter (on line 2) is the declaration.

Notice that this is why the reference to the formal variable on line 11 results in an error - moving upwards we never encounter a var formal!

Global Scope

Immediately Invoked Functions

Functions As Paramters

Named Functions (and Function Hoisting)

Functions That Return Functions

Advanced Concepts

Functions Are Objects

You should understand Objects

Like most things in javascript, functions are objects. That means that they can have properties and methods! function with properties.

Therefore, like other objects, all functions have a .toString, and several other methods. They follow the same prototype inheritence rules as objects and can be used in the same way.

var x = function() {};
x.firstName = "Fred";
x.lastName = "Flintstone";

Most of the time this will be a curiousity and you will not need to use functions as objects. But there are some features that rely on the fact that they can be used in this way.

.call and .apply

this Context Parameter

Function Constructors

Partial Application with .bind

arguments


Functions are a group of statements executed one after another within their own subprogram - think of them like a program within a program. A function can have parameters, that is, when you define a function, you can specify a required list inputs. Importantly, they can also define a return value. In JavaScript, essentially everything is an object, and same goes for functions, and because of this they are deemed "first-class-objects", so they can be stored in variables, passed as arguments to other functions, created within functions, and returned from functions.

Named Functions

To declare or define a named function, we use the keyword, function, followed by a name we give the function. Functions are often by convention named using a verb, because usually they encapsulate the steps required to do somehthing. In short, think of functions as a way to define actions or ask for the state of something, like saveImage();, or, isComplete();.

Here's a very simple function that specifies two parameters and returns the sum of those two parameters:

function add(a, b)
{
	return a + b;
}

This is called a named function, because we're giving it the name add. If we name the function, we can execute it again later in the program by its name.

So once declared, we can then execute it by stating its name, followed by open and closed parentheses () and passing arguments to meet the required parameters. You might also say, instead of execute, invoke, call, or run a function - those terms are synonymous when we speak about executing a function. Here's what executing one looks like:

/*
 * Here, when we define the add function, a and b are called parameters:
 */
function add(a, b)
{
	return a + b;
}

/*
 * Here, when we execute the add function, the values 5 and 5 are 
 * called arguments, which we are passing into the add function: 
 */
var sum = add(5, 5);
console.log(sum); // prints 10;

One thing that often confuses people is the different in nomenclature between parameters and arguments. In the above example, at the point of defining the add function, we specify that the function takes two parameters, a and b. At the point of executing the function, we pass in two arguments, the values 5 and 5. See the comments we've added, above.

By encapsulating a series of statements together, we can reuse the functionality of the steps within the function elsewhere in a program without having to redefine those steps. This helps keep a program more organized and aids in maintainability. Imagine a more complex function:

function isPointInPolygon(point, p) {
    var x = point[0], y = point[1];
    var inside = false;
    for (var i = 0, j = p.length - 1; i < p.length; j = i++) {
        var xi = p[i][0], yi = p[i][1];
        var xj = p[j][0], yj = p[j][1];
        var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }
    return inside;
};

If you later find a better way of expressing this functionality, or if you discovered a bug in your code, by encapsulating these series of statements together in a function, you need only change the code in one place to upgrade or fix its functionality. This form of reuse is described be the D.R.Y principle in design: Don't repeat yourself.

Anonymous Functions

Functions can also be defined anonymously, that is, without a name:

setTimeout(function(){ console.log("Time up!"); }, 1000);

Here, we're executing the built-in setTimeout function, which runs a timer for a specified number of milliseconds, in this case for 1 second. The first parameter of the setTimeout requires us to pass a callback function to be executed once the timer completes, and the second parameter is the number of milliseconds for which the timer will run. In this example, we've defined the callback function inline, without a name, so it is termed an anonymous function.

This example will run a timer for one second, then execute the anonymous callback function, which in turn will call the console.log function, and print the message "Times up!". Because there's no other reference to the callback function, that is, it's not assigned to a variable, and it was not declared with a name, once the timer runs out and the callback function is executed, it is no longer in memeory. This is a powerful pattern you'll see a lot in more advanced JavaScript applications.

Scope

Scope implies what is accessible where. Functions encapsulate their own scope, and functions within functions do the same, but we call those closures. To understand scope, imagine a room within a room, and people in the inner room can see into the outer room, but the people in the outer room cannot see the people inside the inner room. Functions form a closure around themselves to have their own little environment, and variables and values within that closure or scope cannot be seen or accessed outside that function unless the function returns the values:

var x = 1;

function doSomething(){
    console.log('Starting doSomething...');
    console.log(x); // prints 1
    x += 1;
    console.log(x); // prints 2

    var y = 2;
    console.log(y); // prints 2
    console.log('Exiting doSomething...');
}

console.log(x); // prints 1
doSomething();  // see notes inside doSomething()...
console.log(x); // prints 2
console.log(y); // throws a ReferenceError: y is not defined

In this example, x is visible inside the function doSomething() when it is executed, but the variable y, which is declared and initialized inside the function doSomething(), is not visible outside of the function doSomething().

© 2014-2015 Operation Spark