Skip to main content

7 various ways to write JavaScript functions (explained for beginners)

·9 mins
7 various ways to write JavaScript functions (explained for beginners)

How many ways do you already know how to write a function in JavaScript; one, two, three ways?

Well JavaScript can be a crazy programming language sometimes and functions are no exception. There are quite a few different ways to write a function in JavaScript each with their own pros and cons.

So in this article I’m going to show you 7 different ways you can write a function in JavaScript, how they are different from one another and which one you should be using in your code.

But before I show you the various ways, you need to know about a really important JavaScript concept; the this keyword.

The this keyword #

You might have seen the this keyword being used in JavaScript before and basically it refers to some kind of object.

However, within a function the value of this can be different depending on how a function is called.

You can think of this a bit like a hidden function variable and you’ll see as we look at the different ways of writing functions how this can change depending on the way the function is defined and used.

So with this in mind (pun-intended), let’s look at the first way to write a function in JavaScript.

#1 Function Declarations #

The first approach we’re going to look at is probably the first way new JavaScript developers learn to define functions and that is using a function declaration.

A function declaration is written simply with the function keyword, followed by the name of the function and then any arguments the function defines in parentheses.

console.log(add(2, 2));

function add(n1, n2) {
    return n1 + n2;
}

If you were to log out this inside a function written using a declaration then you will find it will give you the global object, in other words the window object when run inside the browser.

The interesting thing about this method is that it allows the function to be hoisted to the top of the scope of where it is defined. This means you can use the function in your code even before it has been written which might be handy if you want to keep all your functions at the bottom of your code to keep them all together. This is in contrast to the next method which does not hoist the function.

#2 Function Expressions #

Function expressions look similar to function declarations but you actually put the function into a variable which can then be called later on.

const fn = function subtract(n1, n2) {
    return n1 - n2;
}

console.log(fn(2, 2));

Another slight variation of this is when we don’t give the function a name and create an anonymous function.

const subtract = function(n1, n2) {
    return n1 - n2;
}

console.log(subtract(2, 2));

As with function declarations, the value of this here will be the global window object in the browser unles you have the function expression assigned to the property of an object.

#3 Function expressions in objects #

You can assign function expressions to the properties of objects you are working with.

const myMath = {
    add: function (n1, n2) { return n1 + n2; },
    subtract: function (n1, n2) { return n1 - n2; },
};

console.log(myMath.add(2, 2));

This allows a nice convenient way to group functions together or to add some functionality to some data you have in an object.

But there’s one difference, unlike function expressions where this will be the global object, the value of this will actually be the object that the function expression is declared on.

This is all to do with the way this inherits it’s value from where the function is actually called from as in this case we’re calling the add or subtract functions from the myMath object so the value of this is set to the myMath object, not the global window object.

Confused?

There’s another way to write functions which has the totally opposite effect when working with objects which we’ll look at in a moment, but first what happens if you give a function expression a name?

#4 Named function expressions #

It might seem a bit weird to give a function a name when it’s defined on an object’s property as we can just use that object property name to call it.

But if we leave it as anonymous function, we can’t refer to the function directly.

We can give the function expression a name on the object so it can be referred to within the function itself which is really useful for recursive functions that call themselves.

const myMath = {
    getFactorial: function factorial(n) {
        if (n <= 1) {
            return 1;
        }
        return n * factorial(n - 1);
    },
}

If you’re thinking “Can’t we just call this.getFactorial() inside the anonymous function instead of naming it?” then you would be absolutely correct and you’re really getting the hang of what the this value represents. I

I’m proud of you.

So another way to write the getFactorial property on the myMath object would be to refer to the same function via the this keyword.

const myMath = {
    getFactorial: function(n) {
        if (n <= 1) {
            return 1;
        }
        return n * this.getFactorial(n - 1);
    },
}

This might save you a few characters worth of space as you don’t need to give your function expressions a name.

Something else that might save you a few more keystrokes is to use shorthand functions.

#5 Shorthand functions #

Shorthand functions were introduced to JavaScript with the ES6 update a few years ago and they allow you abbreviate a function declaration on an object property to just the function name and any parameters it uses.

const user = {
    getFullName(msg) {
        return `${msg} ${this.firstName} ${this.lastName}`
    },
    firstName: 'James',
    lastName: 'Bubb',
}

console.log(user.getFullName());

You might be able to work out from this example function that the this value is set in the same way as before and will give us the user object to work with.

Shorthand functions are also used when we create and use a JavaScript class.

#6 Class and function constructors #

Classes were also introduced in ES6 and provide a way to define a ‘blueprint’ which you can then use to create objects with the data and functions you give it.

For example this is what a User class might look like and it has shorthand functions defined for getFullName as in our previous example and also a special constructor function.

class User {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName(msg) {
        return `${msg} ${this.firstName} ${this.lastName}`;
    }
}

const james = new User('James', 'Bubb');

console.log(james);

The constructor function is used to setup data on the object that is being created and the the value of this here will refer to the new object that is being created, effectively setting new properties on the object we’re storing into the variable james.

It’s worth noting that using a class keyword is exactly the same as defining a function declaration and creating new objects with it using the new keyword.

So the following code does exactly the same thing as above.

function User (firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

const james = new User('James', 'Bubb');

console.log(james);

So if you think you’ve got your head around the concept of this in JavaScript then prepare to have your mind blown as our last way to write functions in JavaScript make this behave completely differently!

## #7 Arrow functions

Another feature introduced in ES6, arrow functions scared the heck out of me when I first encountered them as I was so used to writing functions using declarations and expressions as we’ve already looked at.

You’ve probably seen arrow functions before, they look completely cryptic at first glance.

const square = n => n * n;

Whoa! Where did the function keyword, the parentheses, return statement and curly braces all go!

Arrow functions were introduced to be a compact alternative to function expressions but they can be a bit confusing at first.

The above function is equivalent to this function expression.

const square = function (n) {
    return n * n;
}

There’s a couple of things to bear in mind with arrow functions:

  • You can miss out the parentheses around the parameters in the function if there is only one (multiple parameters need the parentheses)
  • You don’t need a return statement and curly braces if there is just one line of code in the arrow function (any more and you need these)
  • The value of this uses lexical scoping

So what the heck is lexical scope?

Well, it just means the normal rules of setting the value of this as we’ve seen with object properties before doesn’t really apply.

In an arrow function, this gets the value of where it was defined not where it was called from.

If you take the following object with two functions, one an arrow function and one a function expression:

const myMath = {
    add: (n1, n2) => { console.log(this); return n1 + n2; },
    subtract: function (n1, n2) { console.log(this); return n1 - n2; },
};

console.log(myMath.add(2, 2));
console.log(myMath.subtract(2, 2));

Running the code you will notice that the value logged to the console will be different.

The function expression will log the myMath object to the console but the arrow function will log something different - most likely the gloabl window object if you ran this in the global scope or from the browser console. This is something to be aware of but also might prove useful in some siutations.

Which one to use? #

So now you know of lots of ways to write functions in JavaScript but which one should you use?

Well I hate to be that person that says ‘it depends’ but it genuinely does depend on what type of function you are writing and, as we have seen, where you are writing it.

However here is how I choose which function writing approach to use in JavaScript:

  • Try and write a JavaScript class and use constructor and shorthand functions to group related bits of code together
  • Use function expressions (with the function keyword) on objects so you can reference the object they’re defined on using the this keyword
  • Avoid function declarations - hoisting might seem cool but it overall affects the ability to read your code in the future
  • Always go for an arrow function if you are writing something short; they’re compact, readable (once you understand the syntax) and can make use of lexical this

As mentioned lexical scoping can be quite useful sometimes but can also present problems and might require to you bind the value of this to a function and if you’ve got no idea what on earth the bind function does then you should check out this next tutorial which will give you a break down of how to use bind, call and apply in JavaScript.