SpinSpire logo

Functions, IIFE, and pass-by-value

Like most other programming languages, JavaScript supports abstracting (potentially reusable) chunks of code into "functions". But additionally, JavaScript also support "lambda expressions". We will explain what these two mean. They are similar, and yet there are subtle differences. Stay tuned ...

Functions

Let's start with an example:

// function definition
function compare(num1, num2) {
if(num1 > num2) {
return 1;
} else if(num1 == num2) {
return 0;
} else {
return -1;
}
}
// function calls
const n1 = 6, n2 = 5;
const c1 = compare(n1, n2); // c1 is now 1
const c2 = compare(n1, n1); // c2 is now 0
const c3 = compare(n2, n1); // c3 is now -1

As seen in the example above, a function ...

  1. Is a chunk of code with definite boundaries (begin and end) defined once.
  2. Potentially called any number of times (if called more than once, it would be considered reusable).
    • There is a clear distinction between a function definition and a function call.
      • Function definition: A procedure/process made from a chunk of code that is used to complete a task e.g. everything from the first to last curly brace {...} in the example above is the definition.
      • Function call: Actually using the function to complete a task e.g. compare(n1, n2) in example above.
    • The line of code that calls or invokes a function is called caller while the function itself is called callee in that context.
  3. Has a specific function or responsibilities, e.g. this one compares two numbers.
  4. Receives zero or more named parameters, e.g. num1 and num2 above.
  5. Performs some computation, i.e. the body of the function.
  6. At some point, the function returns, i.e. terminates its own execution and returns to execution contexts of the caller.
    • Sometimes it returns a value, e.g. 1, 0, or -1 above.
    • It could also omit returning a value, in which case, the return value is undefined.
    • If you want to return multiple values, all you have to do is return one of the composite types (i.e. array or object)
  7. The function call and its returned value can be used as part of an expression (e.g. 3 * compare(9, 8)). In our example above, we assigned the returned value to c1, c2, or c3, which is but an assignment expression.
  8. In the case above, it has a name. But that's not always the case. it is possible to have functions without names (anonymous functions, explained below).
  9. The caller context passes in actual parameter values that get assigned to the formal parameters once you enter the callee context. In our example, n1 and n2 (with values 6 and 5) are actual parameters that are assigned to num1 and num2, the formal parameters, when execution context enters the function.

Pass-by-value v/s pass-by-reference

num1 = 999;
// Actual parameter
function upgradeCustomer(customer) {
customer.status = "premier";
}

const cust1 = {status: "standard"};
console.log("customer", cust1); // {status: "standard"}
upgradeCustomer(cust1);
console.log("customer", cust1); // {status: "premier"}
function upgradeCustomer(customer) {
customer = "premier";
}

const cust1 = {status: "standard"};
console.log("customer", cust1); // {status: "standard"}
upgradeCustomer(cust1);
console.log("customer", cust1); // {status: "standard"}

[TODO] - provide a graphic.

Anonymous Functions and IIFE

function() {
// ... some code
}
  1. Assign the anonymous function to a variable, and then invoke or call that variable like a function.
    // assign the anonymous function to a variable
    const f1 = function() {
    // ... some code
    };
    f1(); // *call* the variable as a function
  2. But in most cases, we don't have to do this (assign an anonymous function to a variable), because most of the time we are simply passing the anonymous function into the invocation of another function as a parameter, like so:
    document.addEventListener(function (event) { // event callback
    // respond to event
    });
    As you can see above, there's no need to assign the anonymous function above (event callback) to a variable since it, as a value, is getting passed to addEventListener as a function paramter.
  3. The other way lies in the fact that the function definition in JavaScript is technically an expression. Yes, function(){} is actually an expression that has a value! That shouldn't really be surprising since we just assigned the value of that expression to f1 above. So we could eliminate the f1 variable by combining the function definition expression with the function call expression, like so:
    (function() {
    // ... some code
    })(); // IIFE

References:
  1. MDN: Function Expression
  2. MDN: IIFE
  3. MDN: 'apply' function reference