Functions, Scope and Closures


Collapse Content

Functions

Functions in Javascript are first-class objects and can be manipulated and passed around just like any other object.


// JavaScript functions are declared with the function keyword.
function myFunction(word){
    return word.toUpperCase();
}
myFunction("foo"); // = "FOO"

// functions can also be declared like variables:
var sayHello = function(name){
  return "Hi " + name; 
};

// Note that the value to be returned must start on the same line as the 'return' keyword,
// or it will return 'undefined' due to automatic semicolon insertion: 
function myFunction()
{
    return // <- semicolon automatically inserted here
    {
        thisIsAn: 'object literal'
    }
}
myFunction(); // = undefined

// JavaScript functions can be reassigned to different variable names
// and passed to other functions as arguments - e.g. when supplying an event handler:
function myFunction(){
    console.log("this code will be executed after 5 seconds");
}
setTimeout(myFunction, 5000);
// Note: setTimeout isn't part of the JS language, but is provided by browsers and Node.js.

// Function objects don't even have to be declared with a name - you can write
// an anonymous function definition directly into the arguments of another.
setTimeout(function(){
    console.log("this code will be executed after 5 seconds");
}, 5000);

Scope

As mentioned in JS Basics, variables should be declared with var so that they're not automatically placed in the global scope. Their scope will then depend on where they're declared:


// JavaScript has function scope; functions get their own scope but other blocks do not.
if (true){
    var i = 5;
}
i; // = 5  //the variable is within scope here, unlike a block-scoped language
// To prevent temporary variables from leaking into the global scope,
// one-time anonymous functions can be used to wrap the variables:
(function(){
    var temporary = 5;
    // We can access the global scope with the 'global object', which is named 'window' in a web browser.
    //The global object may have a different name in non-browser environments such as Node.js.
    window.permanent = 10;
})();
temporary; // raises ReferenceError
permanent; // = 10

Closures

One of JavaScript's most powerful features is closures: When a function is defined inside another function, the inner function has access to all the outer function's variables, even after the outer function exits.


function delayedGreet(name){
  var prompt = "Hello, " + name + "!"; // #2

  //inner function (they're put in the local scope by default, as if declared with 'var')
  function inner(){
    console.log(prompt);             // #4 (after delay)
  }
  setTimeout(inner, 5000);          // #3
}

delayedGreet("Adam");              // #1

After 5 sec, this gets printed to the console:

Hello, Adam!

What happened:

  1. The bottom line calls delayedGreet(),
  2. delayedGreet assigns a value to prompt.
    2b - The inner() function is created but not executed)
  3. setTimeout() runs with inner() as a parameter. The code then exits delayedGreet and its scope.
  4. After 5 seconds, inner actually runs and accesses prompt. Without closures, prompt would be out of scope, since we left the function 5 seconds earlier. However, because inner() is "closed over" delayedGreet(), it still has access to the prompt variable when it is finally called.

Challenge

Given the following code:

function doThrice(action){
  action();
  action();
  action();
}
function greet(){
  console.log("Hello, how are you doing?");
}

...write one line of code that will print "Hello, how are you doing?" three times.

Please sign in or sign up to submit answers.

Alternatively, you can try out Learneroo before signing up.

Challenge

You found a mysterious piece of convoluted code that calculates and prints theAnswer. What will it print?

universe = 1;  //global variable

function getEverything(){
    var life = 22; //declared in function
    return life;
}

function doubleUniverse(){
    universe = universe * 2;
}

//double universe 4 times
for(var life=0; life<4; life++){  
    doubleUniverse(); 
}

var everything = getEverything();
var theAnswer = life + universe + everything;
console.log(theAnswer);

Please sign in or sign up to submit answers.

Alternatively, you can try out Learneroo before signing up.

Challenge

The function makeAdder, takes in one parameter, x. Fill in the function body so it returns a function that takes in one parameter y and returns the sum of x and y.

For example, calling makeAdder(3); should return a function that returns 3+y, while calling makeAdder(10) should return a function that returns 10+y.

Please sign in or sign up to submit answers.

Alternatively, you can try out Learneroo before signing up.

Comments

Contact Us
Sign in or email us at [email protected]