ref – https://medium.com/front-end-weekly/javascript-functions-are-objects-6affba08ab26
https://hackernoon.com/javascript-and-functional-programming-pt-2-first-class-functions-4437a1aec217
Functions as First-Class Objects in JavaScript: Why Does This Matter?
In computer science, a programming language is said to support first-class functions (or function literal) if it treats functions as first-class objects.
First class objects are entities that can be dynamically created, destroyed, passed to functions, returned as a value, have all the rights as other variables in the language. Same as any other objects. It can have properties, methods.
In other words, this means that JS supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions. In other words,
First-class citizenship, within the world of programming, means that a
given entity (such as a function) supports all the operational properties inherent to other entities; properties such as being able to be assigned to a variable, passed around as a function argument, returned from a function, etc.
Basically, first-class citizenship simply means “being able to do what everyone else can do.”
Excellent! But okay… who cares if JavaScript functions are first-class objects? What does it matter?
The beauty of JavaScript functions enjoying first-class citizenship is the flexibility it allows.
Functions as first-class objects
opens the doors to all kinds of programmatic paradigms and techniques that wouldn’t otherwise be possible.
– Functional programming is one of the paradigms that first-class functions allow.
– Additionally, listening for and handling multiple events by passing callback functions is a useful feature within JavaScript and is achieved by passing a function as an argument to the document object’s addEventListener method.
for example, we have a form with id msgbox. It takes text input, and when you press the submit button, it’ll send a “submit” event.
1 2 3 4 5 |
<form id="msgbox" action="#" method="get"> <label for="msg">your message</label> <input id="msg" value="" /> <button>SEND</button> </form> |
What we try to do, is listening for that event, and get the data from the form.
This is where we pass the SendMessage function as a argument to the addEventListener method.
1 2 3 4 5 |
var msgbox = document.getElementById("msgbox"); // listen for submit events // when submit event happens, call SendMessage function. msgbox.addEventListener("submit", SendMessage, false); |
Where callback functions SendMessage implementation is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function SendMessage(e) { e.preventDefault(); // get the text from the input var msg = document.getElementById("msg").value.trim(); // if text is valid AND if CustomEvent exists... if (msg && window.CustomEvent) { // then we create a custom event var event = new CustomEvent("newMessage", { detail: { message: msg, time: new Date(), }, bubbles: true, cancelable: true }); // then have this event dispatch our 'custom event' e.currentTarget.dispatchEvent(event); } } |
Once we have listened in on the ‘submit’ event, we call SendMessage function in order to create a CustomEvent object with id “newMessage”, stick the user text into it, and then dispatch the event. Now, whoever is listening in on Events with id “newMessage” will be able to receive that event.
So we have a div to put all our text in.
1 |
<div id="newMessage" style="border: 2px solid red"></div> |
Then we have this div listen for “newMessage” events.
Whenever we get “newMessage” events, we want to call newMessageHandler function.
Now, the callback function newMessageHandler has parameter event e, which is the CustomEvent itself.
Take note that the CustomEvent is of an object with properties details, bubbles, and cancelable.
1 2 3 4 5 6 7 8 |
new CustomEvent("newMessage", { detail: { message: msg, time: new Date(), }, bubbles: true, cancelable: true }); |
so in newMessageHandler, we have parameter Event e object. This object is
1 2 3 4 5 6 7 8 |
"newMessage", { detail: { message: msg, time: new Date(), }, bubbles: true, cancelable: true } |
So in newMessageHandler, we then access the msg via detail property via
e.detail.message
1 2 3 4 5 6 7 8 9 10 |
// listen for newMessage event document.addEventListener("newMessage", newMessageHandler, false); // newMessage event handler function newMessageHandler(e) { console.log('div#newMessage received an event'); console.log("Event subscriber on " + e.currentTarget.nodeName+", " +e.detail.time.toLocaleString()+": "+e.detail.message ); } |
– Furthermore, the practices of closure and partial-application/currying would not be possible within JavaScript if functions didn’t enjoy the status of first-class.
ref – http://chineseruleof8.com/code/index.php/2016/01/05/closures-2/
Closure example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function Test() { for (var i = 0; i < 10; i++) { // 1) runs through the i console.log(i); // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 // at this point, i is 10 // 2) after 1 second, then it would execute the callback function setTimeout(function() { // 3) displays the checkmark and 10s console.log('√'); // √ console.log(i); // 10 }, 1000); } } |
output:
The result is:
0
1
2
3
4
5
6
7
8
9
1 second later…
10
10
10
10
10
10
The reason why is because the for loop does 2 things:
1) print out the i
2) set up an async execution of a function that prints i.
The reason why you get 0-9 in the beginning is due to 1). It prints the i right away.
Then it will set up 10 async execution of the callback function.
Once the 1 second passes, it will run the callback.
The reason why the 10 callback functions will all print out all 10s, is because i is already at 10.
The inner function in the setTimeout references the i via parent scope.
The next thing we can do is execute the function expression via IIFE right away like so:
1 2 3 4 5 6 7 8 9 10 11 12 |
for (var i = 0; i < 10; i++) { // 1) runs through the i console.log('for loop: ' + i); // at this point, i is 10 // 2) WE execute our callback right away, and pass in the loop's i // it would use 'parent scope' to see i as is. setTimeout(function() { console.log('callback: ' + i + ' √'); }(), 1000); } |
Now, due to executing the inner function right away, we’ll get the results like so:
for loop: 0
callback: 0 √
for loop: 1
callback: 1 √
for loop: 2
callback: 2 √
When the 1 second passes, it won’t execute the inner function because it was already executed.
The reason why i logs correctly is because we not waiting until it hits 10. We are referencing i right at the moment of the loop, and not after the looping is done.
However, this isn’t exactly what we want.
What we want to do is this. Everytime the for loop sets up an inner function for setTimeout, we know that having the inner function referencing i won’t work because 1 second later, i will already be 10. What we want to do is save the state of the i right at the instant the loop is happening. Hence, what we want to do is:
1) use IIFE to pass in a parameter where we store index i. It will execute this IIFE right away. But since it executes right away, similar to the last example, wouldn’t setTimeOut not be able to execute it?
2) That’s the trick. We return a function to be executed by the setTimeout. 1 second later, the returned function will execute. That function will log index, which has saved state.
1 2 3 4 5 6 7 8 |
for (var i = 0; i < 10; i++) { console.log('for loop: ' + i); // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 setTimeout(function(index) { console.log('execute inner function: ' + index + ' √'); // we return a function for setTimeout to execute return function() {console.log('execute return function: ' + index);} }(i), 1000); // i's value is received via scoping when the callback fun executes. } |
output:
for loop: 0
execute inner function: 0 √
for loop: 1
execute inner function: 1 √
for loop: 2
execute inner function: 2 √
for loop: 3
execute inner function: 3 √
for loop: 4
execute inner function: 4 √
for loop: 5
execute inner function: 5 √
for loop: 6
execute inner function: 6 √
for loop: 7
execute inner function: 7 √
for loop: 8
execute inner function: 8 √
for loop: 9
execute inner function: 9 √
1 second later …
execute return function: 0
execute return function: 1
execute return function: 2
In conclusion, due to us being able to return functions as objects, and passing them as parameters, functions as firsts class objects allows closures to happen.
Currying Example
ref – http://chineseruleof8.com/code/index.php/2019/01/05/currying-js/
Function
In JavaScript, functions are objects (hence the designation of first-class object). They inherit from the Object prototype and they can be assigned key:value pairs. These pairs are referred to as properties and can themselves be functions (i.e., methods).
1 2 3 4 5 6 |
function doIt() { function print() { } } |
And as mentioned, function objects can be assigned to variables, they can be passed around as arguments; they can even be assigned as the return values of other functions. Therefore, functions in JavaScript are first-class objects.
Additionally, functions are a type of object with two special properties, name and code. A function can be named or anonymous. If it’s named then the name will be stored in name property and the code we want to execute will be stored in code. When we try to invoke a function , JavaScript will try to execute the code segment in the code property.
1 2 |
typeof function(){} // "function" typeof "hahah" // "string" |
Since functions are a type of objects, we are able to attach properties to the functions. As you can see in the above image, there are several properties and methods in the “myFunction” function.
We can use the function’s prototype property to store our methods which are common to all objects created using this function. This will help to save all the methods in one place and helps us to reduce the memory footprint of our objects since our methods are stored in the prototype not in the individual objects.
Open up a browser, and open up Elements. Then type in:
1 2 3 4 5 6 |
// implement a function definition. // It will act as the constructor function. function MyFunction() { } // then create an instance from this function constructor var a = new MyFunction(); |
When you analyze the instance of a, you’ll see the structure and hierarchy. The black box is the instance. It has a __proto__ property that is red. It points to the prototype object of MyFunction.
Under the prototype property, you’ll see properties constructor and __proto__.
MyFunction’s constructor property points back to MyFunction’s constructor function.
The __proto__ points down to object prototype.
From an Object structure point of view, in Chrome Elements, it looks like this:
1 2 |
typeof MyFunction // "function" typeof a //"object |
Diagram wise, it looks like this:
We then add a property to the instance. As you can see, the property belongs to the instance. Each instance will have its own “nickname” property.
Finally, we add a function to the prototype. This means all instances of MyFunction can share/use this singular function.
- A function is an instance of the Object type
- A function can have properties and has a link back to its constructor method
- You can store the function in a variable
- You can pass the function as a parameter to another function
- You can return the function from a function
Having functions as type of object helps us to pass our functions into another functions as arguments and open new possibility of writing good programs. I hope you got little more understanding of functions in JavaScript. If you like the article or have any suggestions on improving my article, please reply to this article or contact me.
Storing a function
Functions can be stored in three ways:
store in a variable :
1 |
var fn = function doSomething() {} |
store in an object :
1 2 3 |
var obj = { doSomething : function(){} } |
store in an array :
1 |
arr.push(function doSomething() {}) |
In the first and third example, I used a named function expression.
The function expression defines a function as part of a larger expression. The line of code doesn’t start with function .
Function as an argument
In the next example, the function doSomething is sent as an argument to doAction().
1 2 3 4 |
doAction(function (){ console.log('execute this callback'); }); //doSomething is a callback. |
A callback is a function passed as an argument to another function.
Higher order functions
A higher order function is:
1) a function that takes another function as an input,
2) returns a function or does both.
Let’s look at some built-in methods that are higher-order functions : filter(), map() and reduce().
filter() takes elements out from a list based on a function that decides if the value should be kept.