bg-img

    Created by Mikjail Salazar
    Last Updated on June 30, 2020

    JS Functions Are Objects

    # JavaScript Functions are Objects!

    Yes, in JS world a function is considered an object, and to explain the reason why we will have to learn about types. Types in JavaScript are categorized by:

    • Primitives (string, number, null, boolean, undefined, symbol): these are immutable data types. They are not objects, don’t have methods and they are stored in memory by value.
    • Non-Primitives (functions, arrays and objects): these are mutable data types. They are objects and they are stored in memory by reference.

    To learn more about primitive vs reference values, you can check out this article and our full course on the “tricky parts of JavaScript”.

    As you can see, functions are inside the non-primitive category, which means that when you define a function you are creating an object.

    # Let’s see it in Action!

    So let’s create a function and treat it like if we just created an object.

    Let’s assign a variable and log it:

    // Function declaration.
    function showFavoriteIceCream() {
      const favIceCream = 'chocolate';
    
      console.log(`My favorite ice cream is ${favIceCream}`);
    }
    
    // Let's assign a property.
    showFavoriteIceCream.flavours = ['chocolate', 'vanilla', 'strawberry'];
    
    // Let's log the showFavoriteIceCream function.
    console.log(showFavoriteIceCream);
    
    // Log
    // { [Function: showFavoriteIceCream]
    // flavours: [ 'chocolate', 'vanilla', 'strawberry' ] } -> property assigned

    Here’s what we get:

     The function object contains the assigned property value.

    Let’s assign a function and log it:

    // Function declaration.
    function showFavoriteIceCream() {
      const favIceCream = 'chocolate';
      console.log(`My favorite ice cream is ${favIceCream}`);
    }
    
    // Let's assign a property.
    showFavoriteIceCream.flavours = ['chocolate', 'vanilla', 'strawberry'];
    
    // Let's assign a function.
    showFavoriteIceCream.showFlavours = function () {
      return this.flavours;
    };
    
    // Let's log the showFavoriteIceCream function.
    console.log(showFavoriteIceCream);
    
    // Log
    // { [Function: showFavoriteIceCream]
    // flavours: [ 'chocolate', 'vanilla', 'strawberry' ],
    // showFlavours: [Function] } -> function assigned

    Here’s what this produces:

     Just like before, the function object contains the assigned method.

    As you can see, the showFavoriteIceCream function besides performing an action, is also behaving as an object, we are able to assign properties and methods to it.

    Actually, function are known as first-class objects (or first-class citizens) which means that they can do more than that:

    1. They can be stored in variables.
    // stored in a variable. (Function expression)
    const showFavIceCreams = function () {};
    
    // stored in an array.
    const listOfData = ['vanilla', 5, showFavIceCreams];
    
    // stored in object.
    const thisIsAnObject = {
      showListOfIceCreams: function () {},
    };

    Preview

     The function is assigned to a variable and can be called via that variable.

    1. They can be passed as parameters in another function.
    // Function declaration
    function getFavoriteIceCream() {
      return 'chocolate';
    }
    
    // Function declaration with params
    function logFavoriteIceCream(func) {
      return func();
    }
    
    // Passing getFavoriteIceCream as a parameter in logFavoriteIceCream
    console.log(logFavoriteIceCream(getFavoriteIceCream)); // chocolate

    Preview

     The function is passed as a parameter to another function.

    1. They can return from another function.
    // Function declaration
    function getFavoriteIceCream() {
      const myFavIceCream = 'chocolate';
      // Returns another function declaration
      return function () {
        return 'My favorite ice cream is ' + myFavIceCream;
      };
    }
    
    // storing function returned
    const functionReturned = getFavoriteIceCream();
    
    // executing function returned
    console.log(functionReturned()); // My favorite ice cream is chocolate

    Preview

    A function returns another function as a value.

    Perfect, now we can say that function are objects. Now let’s take a closer look at one of the logs:

     If we console.log the function, it's shown as a "Function" type (instead of just "Object")

    Why are functions logged as Function (and not as “Object” or something similar)?

    Well, it’s because functions are not just objects, they are Function objects, meaning that besides being able to assign properties and methods to them, they also have properties and methods already defined by the built-in Function object.

    Just like arrays are special kinds of objects - arrays also are regular objects with some pre-defined methods available on them. To be precise, for both the Array as well as the Function type objects, the “special” methods are defined on a special prototype.

    And what is a built-in object? In JS there are standard built-in objects upon which other objects are based. Said this, the standard built-in Function is the object upon which functions are based.

    The built-in Function object has properties like name, length and has methods like call, apply and bind. Let’s log some of them to see an existing proof:

    // Function declaration.
    function showFavoriteIceCream(favIceCream) {
      console.log(`My favorite ice cream is ${favIceCream}`);
    }
    
    // Function Properties
    
    console.log('name: ' + showFavoriteIceCream.name); // showFavoriteIceCream
    
    console.log('length: ' + showFavoriteIceCream.length); // 1
    
    // Function methods
    
    console.log('call: ' + showFavoriteIceCream.call); // function call()
    
    console.log('apply: ' + showFavoriteIceCream.apply); // function apply()
    
    console.log('bind: ' + showFavoriteIceCream.bind); // function bind()

    Preview

     We can find all those mentioned properties and methods in the console if we log them.

    name yields the name you gave the function, length shows the number of expected parameters. call(), apply() and bind() can help you with calling the function - you can learn more about these methods (mainly about bind()) in this tutorial.

    Knowing this, we can see functions in a totally different perspective, and here is an example of how we can see it behind the scenes:

     Code defining a function, side-by-side with the console.log() result of that function object being logged to the console (populated with extra methods and properties)

    # Why does all that matter?

    If you’re new to JavaScript, it can be easy to overlook that functions are objects. And that can make it hard to understand why you can do things like myFunction.bind(). Or why functions are reference values.

    Therefore it is key to understand that functions are not “some special thing” in JavaScript but that they are just objects. Objects with special, built-in methods and properties.

    This article was written by Mikjail Salazar, you can visit his LinkedIn profile.