JavaScript


Functions All Versions

1
2
3
E4X
5
5.1
6
7
8

This draft deletes the entire topic.

Introduction

Introduction

expand all collapse all

Examples

  • 21

    When you define a function, it creates a scope.

    Everything defined within the function is not accessible by code outside the function. Only code within this scope can see the entities defined inside the scope.

    function foo() {
      var a = 'hello';
      console.log(a);  // => 'hello'
    }
    
    console.log(a);  // reference error
    

    Nested functions are possible in JavaScript and the same rules apply.

    function foo() {
      var a = 'hello';
      
      function bar() {
        var b = 'world';
        console.log(a);  // => 'hello'
        console.log(b);  // => 'world'
      }
    
      console.log(a);  // => 'hello'
      console.log(b);  // reference error
    }
    
    console.log(a);  // reference error
    console.log(b);  // reference error
    

    When JavaScript tries to resolve a reference or variable, it starts looking for it in the current scope. If it cannot find that declaration in the current scope, it climbs up one scope to look for it. This process repeats until the declaration has been found. If the JavaScript parser reaches the global scope and still cannot find the reference, a reference error will be thrown.

    var a = 'hello';
    
    function foo() {
      var b = 'world';
    
      function bar() {
        var c = '!!';
    
        console.log(a);  // => 'hello'
        console.log(b);  // => 'world'
        console.log(c);  // => '!!'
        console.log(d);  // reference error
      }
    }
    

    This climbing behavior can also mean that one reference may "shadow" over a similarly named reference in the outer scope since it gets seen first.

    var a = 'hello';
    
    function foo() {
      var a = 'world';
    
      function bar() {
        console.log(a);  // => 'world'
      }
    }
    
    6

    The way JavaScript resolves scoping also applies to the const keyword. Declaring a variable with the const keyword implies that you are not allowed to change the value, but declaring it in a function will create a new scope and with that a new variable.

    function foo() {
      const a = true;
    
      function bar() {
        const a = false;  // different variable
        console.log(a);   // false
      }
    
      const a = false;    // SyntaxError
      a = false;          // TypeError
      console.log(a);     // true
    }
    
  • 16

    Currying is the transformation of a function of n arity or arguments into a sequence of n functions taking only one argument.

    Use cases: When the values of some arguments are available before others, you can use currying to decompose a function into a series of functions that complete the work in stages, as each value arrives. This can be useful:

    • When the value of an argument almost never changes (e.g., a conversion factor), but you need to maintain the flexibility of setting that value (rather than hard-coding it as a constant).
    • When the result of a curried function is useful before the other curried functions have run.
    • To validate the arrival of the functions in a specific sequence.

    For example, the volume of a rectangular prism can be explained by a function of three factors: length (l), width (w), and height (h):

    var prism = function(l, w, h) {
        return l * w * h;
    }
    

    A curried version of this function would look like:

    function prism(l) {
        return function(w) {
            return function(h) {
                return l * w * h;
            }
        }
    }
    
    6
    // alternatively, with concise ECMAScript 6+ syntax:
    var prism = l => w => h => l * w * h;
    

    You can call these sequence of functions with prism(2)(3)(5), which should evaluate to 30.

    Without some extra machinery (like with libraries), currying is of limited syntactical flexibility in JavaScript (ES 5/6) due to the lack of placeholder values; thus, while you can use var a = prism(2)(3) to create a partially applied function, you cannot use prism()(3)(5).

  • 11

    Sometimes you don't want to have your function accessible/stored as a variable. You can create an Immediately Invoked Function Expression (IIFE for short). These are essentially self-executing anonymous functions. They have access to the surrounding scope, but the function itself and any internal variables will be inaccessible from outside. An important thing to note about IIFE is that even if you name your function, IIFE are not hoisted like standard functions are and cannot be called by the function name they are declared with.

    (function() {
       alert("I've run - but can't be run again because I'm immediately invoked at runtime,
              leaving behind only the result I generate");
    }());
    

    This is another way to write IIFE. Notice that the closing parenthesis before the semicolon was moved and placed right after the closing curly bracket:

    (function() {
       alert("This is IIFE too.");
    })();
    

    You can easily pass parameters into an IIFE:

    (function(message) {
       alert(message);
    }("Hello World!"));
    

    Additionally, you can return values to the surrounding scope:

    var example = (function() {
       return 42;
    }());
    console.log(example); // => 42
    

    If required it is possible to name an IIFE. While less often seen, this pattern has several advantages, such as providing a reference which can be used for a recursion and can make debugging simpler as the name is included in the callstack.

    (function namedIIFE() { 
        throw error; // We can now see the error thrown in 'namedIIFE()'
    }());
    

    While wrapping a function in parenthesis is the most common way to denote to the Javascript parser to expect an expression, in places where an expression is already expected, the notation can be made more concise:

    var a = function() { return 42 }();
    console.log(a)  // => 42
    

    Arrow version of immediately invoked function:

    6
    (() => console.log("Hello!"))(); // => Hello!
    
Please consider making a request to improve this example.

Syntax

  • function example(x) { return x }

  • var example = function (x) { return x }

  • (function() { ... })(); // Immediately Invoked Function Expression (IIFE)

  • var instance = new Example(x);

  • Methods

  • fn.apply(valueForThis[, arrayOfArgs])

  • fn.bind(valueForThis[, arg1[, arg2, ...]])

  • fn.call(valueForThis[, arg1[, arg2, ...]])

  • ES2015+ (ES6+):

  • const example = x => { return x }; // Arrow function explicit return

  • const example = x => x; // Arrow function implicit return

  • const example = (x, y, z) => { ... } // Arrow function multiple arguments

  • (() => { ... })(); // IIFE using an arrow function

Parameters

Parameters

Remarks

For information on arrow functions, please view the Arrow Functions documentation.

Still have a question about Functions? Ask Question

Topic Outline