Abstraction In Javascript via Higher Order Functions

What is Abstraction In Javascript?

Abstraction In Javascript

We have seen how to create and execute higher order functions In Javascript. Generally speaking, Abstraction In Javascript higher order functions are usually written to abstract common problems. In other words, higher order functions are nothing but defining abstractions In Javascript.
In this section we discuss the relationship that higher order functions have with the term abstraction In Javascript.

Abstraction In Javascript

Wikipedia helps us by providing this definition of abstraction:
In software engineering and computer science, abstraction is a technique for managing complexity of computer systems. It works by establishing a level of complexity on which a person interacts with the system, suppressing the more complex details below the current level. The programmer works with an idealized interface (usually well defined) and can add additional levels of functionality that would otherwise be too complex to handle.

It also includes the following text, which is what we are interested in:
For example, a programmer writing code that involves numerical operations may not be interested in the way numbers are represented in the underlying hardware (e.g., whether they’re 16 bit or 32 bit integers), and where those details have been suppressed it can be said that they were abstracted away, leaving simply numbers with which the programmer can work.
This text clearly gives the idea of abstraction. Abstraction allows us to work on the desired goal without worrying about the underlying system concepts.

Abstraction In Javascript via Higher Order Functions

In this section we will see how higher order functions help us to achieve the abstraction concept we discussed in the previous section. Here is the code snippet of our forEach function.

const forEach = (array,fn) => {
for(let i=0;array.length;i++)
fn(array[i])
}

The preceding forEach function here has abstracted In Javascript away the problem of traversing the array. The user of the forEach API does not need to understand how forEach has implemented the traversing part, thus abstracting In Javascript away the problem.

Note in the forEach function, the passed function fn is called with a single argument as the current iteration content of the array, as you can see here:
. . .
fn(array[i])
. . .
So when the user of the forEach function calls it like this:

forEach([1,2,3],(data) => {
//data is passed from forEach function
//to this current function as argument
})

Abstraction In Javascript Example

forEach essentially traverses the array. What about traversing a JavaScript object? Traversing a JavaScript object has steps like this:

1. Iterate all the keys of the given object.
2. Identify that the key belongs to its own object.
3. Get the value of the key if Step 2 is true.

const forEachObject = (obj,fn) => {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
//calls the fn with key and value as its argument
fn(property, obj[property])
}
}
}

Note forEachObject takes the first argument as a Javascript object (as obj) and the second argument is a function fn. it traverses the object using the precedng algorithm and calls the fn with key and value as its argument, respectively.

Here they are in action:

let object = {a:1,b:2}
forEachObject(object, (k,v) => console.log(k + ":" + v))
=> a:1
=> b:1

Cool! An important point to note is that both forEach and forEachObject functions are higher order functions, which allow the developer to work on task (by passing the corresponding function), abstracting away the traversing part! Because these traversing functions are being abstracted away, we can test them thoroughly, leading to a concise code base. Let’s implement an abstracted way for handling control flows.

For that, let us create a function called unless. Unless is a simple function that takes a predicate (which should be either true or false); if the predicate is false,

unless function javascript

const unless = (predicate,fn) => {
if(!predicate)
fn()
}

With the unless function in place, we can write a concise piece of code to find the list of even numbers. The code for it looks like this:

forEach([1,2,3,4,5,6,7],(number) => {
unless((number % 2), () => {
console.log(number, " is even")
})
})

This code, when executed, is going to print the following:

2 ' is even'
4 ' is even'
6 ' is even'

In this case we are getting the even numbers from the array list. What if we want to get the list of even numbers from, say, 0 to 100? We cannot use forEach here (of course we can, if we have the array that has [0,1,2…..,100] content). Let’s meet another higher order function called times. Times is yet another simple higher order function that takes the number and calls the passed function as many times as the caller indicates

times function javascript

const times = (times, fn) => {
for (var i = 0; i < times; i++)
fn(i);
}

The times function looks very similar to the forEach function; it’s just that we are operating on a Number rather than an Array. Now with the times function in place, we can go ahead and solve our problem at hand like this:

times(100, function(n) {
unless(n % 2, function() {
console.log(n, "is even");
});
});

That’s going to print our expected answer:

0 'is even'
2 'is even'
4 'is even'
6 'is even'
8 'is even'
10 'is even'
. . .
. . .
94 'is even'
96 'is even'
98 'is even'

With this code we have abstracted javascript away looping, and the condition checks into a simple and concise higher order function!

Having seen a few examples of higher order functions, it’s time to go one step further. In the upcoming section, we will discuss real-world higher order functions and how to create them.

Keywords;

Abstraction In Javascript Example,Abstraction In Javascript,abstraction in javascript function,abstraction program in javascript,Abstraction In Javascript via Higher Order Functions,