DevBlog of Árpád Poprádi

The Javascript Function

Functons are powerful because they bundle many aspects of information processing in a concise syntax. On the other hand this terseness is an obstacle to understanding them completely. In this post I build up the function mechanic from the very basic up to an introduction to Functional Programming concentrating on the most important elements of the function machinery. I use ES2015 syntax because its clearer. The interested reader is highly encouraged to play with the code snippets and form his own experiments and thoughts! I write things that are in the JavaScript Engine and not visible for us mortal developers in upper case (e.g. SCOPE) like Death speaks on Terry Pratchett's Discworld. The scope as a term kept in lower case.

 

Can you imagine a program without a single function?

Do you know that the Turing machine doesn't know the concept of function? To compute everything computable it doesn't need the function concept. There are some funny videos on YouTube how to implement a specific function in the Turing machine.

Functions are more about humans then machines.

Functions are abstraction tools for us. The goal of an abstraction is to give a simpler access. For example variables abstract data. Functions abstract doing. Their simple access is called the function expression.

The Function Definition

Here is the simplest function definition:

function f(){};

This code does nothing visible... but the function exists already!

Functions are objects.

They have properties from Function.prototype and all the power of a JavaScript object.

Why is an empty function definition so long? Let's see its parts! The interesting aspects here are compressed into the two bracket pairs. Brackets indicate some barrier. What kind of barriers can they be?

Scope

Out of a function definition {} means a code block as follows:

{} defines a visibility barrier. Inside other things are visible then outside. We name the collection of visible variables scope. Unfortunately there is no way to see the SCOPES as objects using JavaScript. They are hidden within the JavaScript Engine. In this example there are two SCOPES: one for the outside and one for the inside of the block. Each INSTRUCTION that the JavaScript Engine executes is related to one SCOPE.

How are the SCOPES related to each other? For example:

{} is a one way visibility barrier. A SCOPE is a layered structure built up from other SCOPES. A scope layer sees its own variables and can see out but not inside into a contained scope. The inner variables hide the outer ones. It can be imagined as follows:

In the above examples the BLOCK LOCAL SCOPE will be garbage collected after use. What would it be if after its first usage it could be reused again? This is actually a great idea as we will see later but a more advanced structure will be needed. I will name it SCOPE_DB. For example:

SCOPE_DB is a layered hierarchical database that maps variables to their values within the JavaScript Engine. A SCOPE is the visible part of SCOPE_DB for a specific INSTRUCTION.

Lexical Scoping

Lexical Scoping is the name of the seen scoping rules. We have seen already some rules:

  • Each block sees its own variables.
  • The inner block sees the the outer blocks.
  • The outer blocks don't see inside of the inner blocks.

It's called lexical scoping or static scoping because what the INSTRUCTIONS will see from a specific point of the code is determined by a simple code reading at compile time. The SCOPE is created during runtime but what it will see is determined at compile time. All the rules apply to the functions.

Parameters

As we see now a function is an objectified, named block. Getting back to the function definition the next interesting element is the () parenthesis. As everybody knows it is the place for the parameters. But why are they needed? This question sounds strange probably, but think about it: we have already a way to access things from outside of the function. The function block sees the containing block anyway, if a variable get a new value and the function uses that variable then it changes its doing. More than that the function can modify any variable in its CURRENT SCOPE. It's a very dangerous freedom but JavaScript allows it. Why do we need another way to get in touch with the outer world? This question leads us to features that code blocks don't have.

The Function Expression

Executing a code block's opening bracket creates a new LOCAL SCOPE and the closing bracket closes it. Every INSTRUCTION in between will be executed. This is not really an abstraction it's only encapsulation.

But a function definition doesn't mean function execution, there is no visible effect on the world. The function expression prolonges and can repeate function execution/function call in various ways. For example:

f(arguments);

There is no function body, no function keyword but possible arguments. They can be different for each call in contrast to the parameters, which are fixed in the function definition:

function f(parameters) {
...
}

The function expression is the abstraction in use.

Lexical Scoping rules extended

  • Each block sees its own variables.
  • The inner block sees the outer blocks.
  • The outer blocks don't see inside of the inner blocks.
  • The function parameters belong to the function body block.

The Function Call

Neither a function definition nor a function expression has a SCOPE. Only a function call has a SCOPE. The function call is the abstraction in action literally. We have seen that a new LOCAL SCOPE will be created by the JavaScript Engine only if a code block is going to be executed.

Closures are a consequence of the facts that functions are objects and we use lexical scoping

The functions are objects, therefore they can be assigned to outside of the defining block as in the following example:

The scope at executing line 5 after calling fun/f:

According to lexical scoping the BLOCK SCOPE must exist even after the block is already finished because it is needed by the f(1) CALL SCOPE.

A CLOSURE is a SCOPE kept alive to let a function call have access to it.

The Object Oriented way to feed the SCOPE: this

this is the Object Oriented specific way how functions access variables. Like here:

The Object Oriented modelling uses the functions in a specific way and the JavaScript functions are prepared for that useage but for a function itself this is only another way to get in touch with the outer world but a somewhat different way as we have seen it so far.

Can you spot where is this defined in the code above?

Nowhere. But the code works and this refers to o as it's expected. this is in the SCOPE but not via lexical scoping. Above this is set by the JavaScript expression:

o.f()

But because this is only another parameter it can be set other ways too. For example arrow functions get this lexically scoped from the defining SCOPE. The inc function here is an arrow function:

The lexically scoped this comes very handy in situations like the one above, where all we want is a simple helper for another function and the full flexibility of function would bloat the code with syntactic noise. For such tasks arrow functions have a very nice syntax. More about them here.

Here are all of the this binding rules:

  1. new rule: A function call after new gets the newly created object as this
  2. explicit rule: A function called with apply, call, or bind has bound its this to the given object. A binding with bind is not to rebound.
  3. implicit rule: A function call in the form obj.someFunction() has its this bound to obj.
  4. default rule: All other cases (e.g someFunction() ) mean that this is set to undefined in strict mode or to the global object in non-strict mode.
  5. arrow function rule: this within an arrow function is fixed to the value of this in the arrow function creation SCOPE.

It is somewhat overwhelming. Knowing this is a must but teaching it is beyond the possibilities of this post. For details click here.

Comparison of the different access ways

Here is a summary how a function call can get something in its SCOPE:

 

The JavaScript function has many ways to get in touch with the outer world. Which way is good for what?

this powers the Object Oriented paradigm.

Closures power privacy. For having something private a JavaScript object is unsuitable. A SCOPE attached to a function and seen by no one but that function solves the problem:

In the example above we carry along the state two ways: The public one is accessed by this and the private one is the CLOSURE created by the createObjectWithPrivacy call.

"Closures are the poor man's objects and vice versa."

Cool, isn't it?

It will be cooler. Arguments too can carry along a state! And arguments power the function expressions.

Functional Programming

All the wide variety of access methods mentioned until now, mean a lot of possibility for unwanted changes and obscured dependencies.

One way to master the chaos is using only some proven way to let the function interact with the rest of the universe.

Take a look at mathematics. Mathematicians have managed to work together on the first open source project of humanity over centuries all over the world. They have to have the methods to not to step on eachothers toes and build something new on the top of the work of others. Their management of their formulas is what we call today Functional Programming.

Have you noticed that I did not say anything about the return statement all the way?

Because the return statement is not so dangerous: the caller can ignore the return value, but can't ignore the side effect. In Functional Programming the return statement gets finally its well deserved place. The return statement defines the value of the function expression and in Functional Programming it is the only way to get a visible effect on the world from a function call.

What is Functional Programming in JavaScript?

In short, a self-chosen straitjacket for the greater good. We abandon a lot of code bungling possibility to have the pieces we trust and can be built safely together.

More explicitly

  1. Functions are objects (JavaScript supports it)
  2. Input is immutable (No JavaScript support, it must be forced by the programmer)
  3. Output is determined by the input.
  4. Input and output are well typed (No JavaScript support, and it's often not needed to do something useful) means the compiler can check the correctness of the input usage and the type of the output.

In JavaScript a function can have input in 3 ways:

  • by arguments
  • by this
  • from out of function body by lexical scoping

Functions with the property 2. and 3. above are called pure functions. They don't pollute their surrounding environment and are determined by the input.

The advantages of Functional Programming

From 1. above follows;

  • A new level of expressiveness.

From 2. above follows;

  • No side effect. No input will be changed regardless where it comes from.
  • Each function is automatically parallelizable.

From 3. and 4. above follows;

  • Each function can be reasoned about on its own.

From 2. and 3. and 4. above follows;

  • Each function can be reasoned about on its own and let all other functions reason about useing the same input. So the reasoning is composable.

The JavaScript function is prepared for both Object Oriented and Functional Programming

This is great because each paradigm has its own strength.