JS Functions Are Objects
Unknown to many JavaScript developers, functions are objects in JS. This matters and has important implications which are discussed here.
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.
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:
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:
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:
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
They can be passed as parameters in another function.
// Function declarationfunction getFavoriteIceCream() {return 'chocolate';}// Function declaration with paramsfunction logFavoriteIceCream(func) {return func();}// Passing getFavoriteIceCream as a parameter in logFavoriteIceCreamconsole.log(logFavoriteIceCream(getFavoriteIceCream)); // chocolate
Preview
They can return from another function.
// Function declarationfunction getFavoriteIceCream() {const myFavIceCream = 'chocolate';// Returns another function declarationreturn function () {return 'My favorite ice cream is ' + myFavIceCream;};}// storing function returnedconst functionReturned = getFavoriteIceCream();// executing function returnedconsole.log(functionReturned()); // My favorite ice cream is chocolate
Preview
Perfect, now we can say that function are objects. Now let's take a closer look at one of the logs:
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 Propertiesconsole.log('name: ' + showFavoriteIceCream.name); // showFavoriteIceCreamconsole.log('length: ' + showFavoriteIceCream.length); // 1// Function methodsconsole.log('call: ' + showFavoriteIceCream.call); // function call()console.log('apply: ' + showFavoriteIceCream.apply); // function apply()console.log('bind: ' + showFavoriteIceCream.bind); // function bind()
Preview
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:
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.