JavaScript functions

Table of Contents

Function Expression

A function expression starts with the keyword function followed by the function arguments in parentheses and the function body in curly braces:

const square = function(x) {
  return x * x;
};

console.log(square(4));  // >> 16

Function Scope

  • Each function defines a scope
  • Local variables of a function are not visible outside of the function
const a = "Hello ";          // a has global scope

const f = function(b) {      // b is local to f
  const c = "!";             // c is local to f
  console.log(a+b+c);
};

f("World");                 // >> Hello World!
console.log(typeof b);      // >> undefined
console.log(typeof c);      // >> undefined

Lexical Scope

Variables have lexical (static) scope, i.e., the scope of a variable is determined by the code context of the variable:

const a = 2;

const f = function(b) {
  return a+b;
};

console.log(f(7));      // >> 9

const g = function() {
  const a = 5;          // a is hiding the global variable inside g
  return f(7);          // but the global variable is used inside f
};
console.log(g());       // >> 9

Nested Scope

  • Blocks and functions can be created inside other blocks and functions
  • Each local scope can access the variables from the surrounding scopes
const a = 2;

const f = function(b) {
  let x = 1;

  const g = function() {    // g has access to the local variables of f and to
    x *= a;                 // the variables of the global scope
  };

  while (x < b) g();
  return x;
};
console.log(f(100))        // >> 128

Functions are Objects

Functions are objects, hence they can be used as arguments and return values of other functions (higher-order functions)

// Function as argument
const repeat = function(action, n) {
  for (let i = 0; i < n; i++) action();
};

const sayHello = function() {
  console.log("Hello");
}
repeat(sayHello, 3);                   // >> Hello Hello Hello

// Function as return value
const formatter = function(prefix, suffix) {
  return function(s) {
    return prefix+s+suffix;
  }
};

const format = formatter("'", "!'");
console.log(format("Hello World"));    // >> 'Hello World!'

Closure

A function that references a specific instance of a local variable in an enclosing function is called a closure:

const counter = function(init) {
  let val = Number(init);
  return function() {
    return ++val;
  };
};

const countA = counter(12);    // countA references a specific instance of val
console.log(countA());         // >> 13
console.log(countA());         // >> 14

const countB = counter("6");   // countB references another instance of val
console.log(countB());         // >> 7
console.log(countA());         // >> 15

Function Declaration

A function declaration defines a variable which points to the given function:

// Declare f to be a function
function f() {
  return "I'm a chicken";
}

console.log(f());      // >> I'm a chicken

// The variable f can be reassigned
f = function() {
  return "I'm a fox";
}

console.log(f());      // >> I'm a fox

Function Declarations are Hoisted

Function declarations are not part of the regular top-to-bottom flow of control:

// The function f can be used before it is declared
console.log(f(4));     // >> 48

function f(a) {
  return g() * a;
};

function g() {
  return 12;
}