Deeper Dive Into Javascript Functions – Introduction

Functions are Objects in Javascript. Functions have properties and methods. They can be passed around like any other Javascript objects and can also be defined at runtime. They are so powerful that we can write applications without needing any other Javascript built-in objects. We need to have a deeper understanding of  how Functions work in Javascript to become better Javascript programmers. I divided the entire subject into small articles. I will start with the basics like Function structure, return statement and etc. I assume that you have a basic knowledge of Javascript. Mozilla Developer Network is a great place to start learning Javascript.

Article Content:

  • Introduction” to Javascript
  • Javascript Scope
  • Method Context in Javascript
  • How to avoid ‘Side Effects’ in your Functions
  • Pure Functions (Stateless Functions)
  • Lambdas
  • Immediately Invoked Function Expressions (IIFE)
  • Closures and Module Pattern
  • Function Polymorphism
  • Method Dispatch
  • Functional Programming in Javascript
  • Partial Applications and Currying
  • Promise

Function Declarations vs Function Expressions

Declaring a function is more like a declaring a variable. It starts with function, then comes a function name.

/* Function Definition Example */
function bar() {
  // function body
}

Functions without return statement always return default value, which is undefined. The only exception is when a new object  is created calling a constructor function using new keyword. In this case default return value will be the value of this.

function Intro() {
  console.log(this);
}
var intro = new Intro();  // Intro {}

Functions receive parameters only by value, even if the function parameter is an object reference, the value which is passed is not an actual object but the reference to the object outside the function.

Conditional Function Definitions should be avoided. It will fail in Chrome, Safari and Internet Explorer, while it works on Firefox.

var number = 10;

if(number > 5) {
function compare() {
  return "bigger";
 }
} else {
function compare() {
  return "smaller";
 }
}
/* it supposed to return 'bigger' but it fails to do so */
compare(); //smaller

This is a Function Expression syntax (EcmaScript 5.1 Language Spec):

FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

So all the examples below are correct examples:

1) function expression() { //function body }
2) function() { //function body }
3) var expression = function() { //function body }
4) var expression = function exp() { //function body }

1st Statement is similar to a Function Definition, except Identifier is optional for Function Expression. You should assign functions in 1st and 2nd statements to variables, if you want to access them later. 4th statement is an example to the Named Function Expressions. Identifier here is only accessible within the function.

var namedFunctionExpression = function nfe() {
    return 1;
}
namedFunctionExpression(); //1
nfe(); // you will get a ReferenceError

By the way, conditional assignments would work with Function Expressions. We can modify the example we used for Function Declarations.

var number = 10;

if(number > 5) {
var compare = function() {
  return "bigger";
 }
} else {
var compare = function() {
  return "smaller";
 }
}
compare(); //bigger

Function expressions are very useful to design a well-architected APIs using method literals.

var arithmeticsAPI = {
    add : function() {},
    subtract : function() {},
    multiply : function() {},
    divide : function() {}
};

All the methods in the arithmeticsAPI object literal are called Method Literals.

 

Execution Context

(Section 10.3 – http://bit.ly/1NTuVX2)

When we talk about an Execution Context, we talk about the context where your Javascript code runs. There are only 2 contexts.

  1. Global Context: It is where your entire code gets executed once. This is a default context. Javascript Engine creates the Global Context when it starts the code execution process.
  2. Local Context (Function Context): Function Context is created whenever a function is called. This is how we create a private scope.

According to the Spec (Section 10.3 – http://bit.ly/1NTuVX2 ):

Active execution contexts logically form a stack. The top execution context on this logical stack is the running execution context.

Whenever a new Local Context is created it is pushed to the top of the stack and becomes the currently active stack. A Global Context is always at the bottom of the stack. Throwing exception and using a return statement inside the function will exit the Execution Context.

Execution Context contains 3 components to keep track of the state: LexicalEnvironment, VariableEnvironment and ThisBinding. What happens when an execution context is created?

  1. ThisBinding is set: set ThisBinding to a caller’s this argument. If this is null or undefined ThisBinding will be set to the global object.
  2. VariableEnvironment and LexicalEnvironment are defined: Their values are set to LocalEnvironment and are always the same at this stage.
  3. Declaration Bindings are performed: Variables, Functions and Function parameters are added as bindings in the VariableEnvironment’s Environment Record which is a record at the top of the scope chain.

Check out the ECMAScript Spec for more details (http://bit.ly/1NTuVX2).

Hoisting

Another important thing we need to mention is Hoisting. We can either say Variable Declarations and Function Declarations are lifted to the top of the containing scope and that is correct. On the other hand, if you really want to know how Javascript Engines deal with Variable and Function Declarations, you will see, it is different but the result is the same. So, there is no structural change is made to the original code. Nothing is lifted to the top of the containing scope. Javascript executes code in 2 stages.

  1. Definition Stage: Define Variables, Functions and Function parameters as I explained in the “Execution Context”.
  2. Execution Stage: It basically executes the code. Assign values to declared variables, build references to functions.

So called hoisting is happening at the Definition Stage. Variables are declared and “undefined” value is assigned to them.

Reference: