JavaScript Functions

An opinionated guide for beginners

Created by Tomasz Primke / tprimke (at) gmail (dot) com

The last update: 3rd March 2015

Plan

Part I : Fundamentals

  1. Definition
  2. Creating functions
  3. Variables and scopes
  4. Arguments

And then, the second part...

Part I : Fundamentals

Definition

What is a function?

A function is a block of code, with optional arguments, that can be called.

In JavaScript, functions can cause side effects.

Functions are used for:

  • Code reuse
  • Methods of objects
  • Callbacks

Creating functions

Function expressions:

Function statements

What's the difference between function expressions and function statements?

The function defined by expression, cannot be called before it was defined.

The function defined by statement, can be called.

Variables and scopes

You probably know, what variables are.

In JavaScript, you should learn how they are bound with scopes.

But what are scopes?

Scopes are blocks of code, where variables are available.

Local variables (1)

Both i and prod variables are local.

The factorial variable is global.

(Yes, the factorial variable is bound to a function.)

Local variables (2)

All the local variables are declared at the beginning of their function.

It means, that this code:

is equivalent to this code:

A good practice is to declare all the local variables at the beginning of a function.

That's the way JavaScript sees those variables.

Global variables

In this example, both variables i and prod are global.

The reason is simple: they are introduced in the factorial function without the var statement.

Any variable introduced without the var statement, is global.

In general, it's quite easy to forget the var statement, and introduce a global variable.

For example, when you make a typo:

(A tip: the prod variable has a typo in the loop.)

Yes, that's sucks. :-(

Final remarks

Use local variables, whenever it's possible.

Declare all your local variables at the beginning of your functions.

In ES 6, there are new ways to use local variables.

Function arguments

Function arguments are values passed to the function during a function call.

The n is an argument.

In general, arguments can be passed by value, and by reference.

In JavaScript, all primitive values (numbers, strings, booleans, null and undefined) are passed by value.

While passing an argument by value, a copy of the value is made, and the copy is passed to the function.

It means, that the function may change the passed value, and it won't affect the original value.

As long, as you pass a primitive value to the function, you can do whatever you want with the value, and it won't affect the original variable.

On the other hand, not primitive values are passed by reference.

Arrays and objects are not primitive values.

It means, that they can be changed in the function's body.

Optional arguments

And what when you don't pass some arguments?

When an argument is not passed, it's undefined.

This feature can be used to set default values for arguments.

Default values

When pref is undefined (since it hasn't been passed), it will be set to "Hello, ".

(In ES 6, there are other ways to use default values. It will be discussed in the advanced part of this guide.)

Arbitrary number of arguments

In JavaScript, you can pass as many arguments to the called function, as you want.

(Regardless of the number of declared arguments.)

All the passed arguments are available in the arguments object.

(Although the arguments object looks like an array, it's not an array.)

Part II : Advanced material

  1. Functions as arguments
  2. Returning functions as results
  3. API
  4. ES 6 goodies

Functions as arguments

In JavaScript, everything is an object.

It means, that functions are also objects.

And they can be passed as functions' arguments, just as any other objects.

Example:

Anonymous functions

But functions don't need any names:

In ES 6, the fat arrow syntax allows to create anonymous functions easier.

Closures

In JavaScript, each function has its own (local) scope.

What would happen, if we defined a function within a body (scope) of another function?

The showMsg function is defined in the body of the queueMessage.

In the showMsg function, the text variable is used.

This variable is defined in the scope of the queueMessage function.

We say, that the showMsg function closes over the variables text, msg and delay.

Thus, it is called a closure.

What's so great about closures?

They encapsulate variables.

In a closure's body, all the enclosed variables are available.

But if we have a closure, we cannot touch them!

Which raises another question:

Is it possible to have a closure?

The module pattern

Let's analyse the code:

This is a variable definition:

Whatever is in the perenthesis, cannot be touched from outside.

This is a function in the parenthesis:

It's an anonymous function.

After the perenthesis, the function is called.

So, the module variable will be bound the value returned by the function.

The returned value is an object, with one property: greet.

And the greet property is a closure!

The closure greet has access to the counter variable.

This variable is inaccessible for the user of the module object.

So, the counter variable is private for the module.

Usage

Anonymous functions and closures are used:

  • for callbacks / handlers
  • for encapsulation (like in the module pattern)

Functions as results

The standard way:

Using a function as the returned value:

Functions returning other functions are called higher-order functions.

Currying

We have a function, that takes multiple arguments.

Then, we transform this function into a sequence of functions, which takes only one argument.

That's currying.

What we did to the addPrefix function, was currying.

After currying, calling functions changes:

Currying can be used for ease creation of functions.

API

API is short for "application's programmer's interface".

For this guide, function's API is its signature: the name and arguments (both number and order).

Why is it important to design a good API?

The better API, the easier it is to use, understand and maintain.

names

The general rule: make up some convention and stick to it.

The following examples are just proposals.

Does the function do something? Use a verb.

Does the function returns something? Use a noun.

Camel case or dashes?

Number of arguments

No arguments = no problem.

One argument = no problem.

More arguments = you have to think about it.

What's the problem?

The order of arguments, of course!

No currying: the least changing argument should come last.

Now, let's consider this:

We can easily drop the second argument.

If we use some reasonable default, we can make our job easier.

Currying: the least changing argument should come first.

Now, let's consider this:

We can easily create a function with a fixed value for the first argument.

If we use some reasonable (default) value, we can make our job easier.

Reducing number of arguments

Good luck with remembering the order of flags...

Much better!

ES 6 goodies

Fat arrows

Default values

Spread operator

The arguments object is no longer needed.

Destructuring

It is also possible with arrays:

Object literals

let

let lets you define variables in a block scope.

No more worries about vars visible in whole function!

const