Skip to content

Instantly share code, notes, and snippets.

@nultinator
Created March 29, 2024 17:11
Show Gist options
  • Save nultinator/7582fce0708ec1daedaf5d4d4cd2c2cb to your computer and use it in GitHub Desktop.
Save nultinator/7582fce0708ec1daedaf5d4d4cd2c2cb to your computer and use it in GitHub Desktop.

Understanding JavaScript: Scary Looking Functions

header-image

Table of Contents

Introduction

Functions are used all the time in programming all over the world. Anonymous functions are used pretty widely in many languages but none look quite strange and intimidating as they look in JavaScript. As far as general concepts go, you can basically think that there are two types of functions, declarative and anonymous. Declarative functions are given a name have a basic structure that is easy to follow. When dealing with Anonymous functions in JavaScript, we often run into the IIFE (Immediately Invoked Function Expression). IIFEs are executed as soon as they are created. While this can a convenient way to write code, IIFEs can be quite a big turnoff for people coming from other languages.


What are Declarative Functions?

Declarative functions are pretty easy to follow. Each function has a name, can take parameters, and uses top down execution. You create a function with the function keyword. Followed by the function keyword are parentheses, () and within them, we put our parameters. Each of these functions has a name, so we can reuse them as many times as want.

Here is a simple declarative function that counts down to zero:

function countdown(number) {
    while (number > 0) {
        console.log(number);
        number--;
    }
    console.log("Blastoff!")
}

countdown(10);

As you can see, after declaring the function, we need to call it using countdown(10) which passes the number 10 into the function. Declarative functions are easy to understand and they're best suited for reuse.


What are IIFEs?

An IIFE (Immediately Invoked Function Expression) can be quite a bit tougher to follow. With an IIFE, we actually put parentheses with an arrow followed by curly braces() => {}. At the end of the function, we run it using an additional parentheses. An IIFE typically looks like this (() => {})();. The logic of the function goes within our curly braces. These functions are not saved in the namespace so they are not reusable. IIFEs are best used when you only want to do something once. These functions are best used for saving memory on the machine and keeping the namespace clean.

Here is our countdown as an IIFE:

(() => {
    let x = 10;
    while (x > 0) {
        console.log(x);
        x--;
    }
    console.log("Blastoff!");
})();

This function will run as soon as it is declared but we are not able to reuse it. This sort of thing is best suited for main functions and other portions of our code that only get used once. Once an IIFE goes out of scope, the rest of the program forgets about the function.

Comparing IIFE and Declarative Functions

Aspect IIFEs Declarative Functions
Execution Execute immediately Must be explicitly called
Scope and Privacy Logic is forgotten when it goes out of scope Function names are remembered in the global scope
Hoisting Cannot be hoisted, executed exactly where they are in the code Hoisted, you can declare a function at the bottom of a file and call it from the top
Use Cases Used when an immediate, one-time execution is needed Great for reusable code blocks, you can call them as many times as you want

Practical Applications and Examples

In practice, IIFE is best suited for one-time use of a function and Declarative functions are best suited for reuse. Let's get a lot done with a small amount of code! First we need to create a new folder for a JavaScript project. Then initialize it with the following command:

npm init --y

Now, we'll add the headless browser, Puppeteer to our project folder.

npm install puppeteer

Now simply create a file with the following code:

const puppeteer = require("puppeteer");
//async declarative function that goes to a page and takes a screenshot
async function takeScreenshot(page, url, filename) {
    await page.goto(url);
    await page.screenshot({path: `${filename}.png`, fullPage: true});
}
//declarative function to give us ranges
function range(start, end) {
    let range = [];
    for (let i=start; i<end; i++) {
        range.push(i);
    }
    return range;
}
//async IIFE to be used as our main function
(async () => {
    //open a headless browser
    const browser = await puppeteer.launch({headless: true});
    //create a new page
    const page = await browser.newPage();
    //url to go to
    const url = "https://quotes.toscrape.com/page"
    //use our declared functions over and over again
    for (const i of range(1, 11)) {
        await takeScreenshot(page, `${url}/${i}/`, `quotes-${i}`);
    }
    //close the browser and exit the IIFE
    await browser.close()
})();

In this example, we create two declarative functions: takeScreenshot() and range().

  • takeScreenshot() takes three arguments:
    • page: the page we're currently scraping with
    • url: where we want to go
    • filename: the name of our screenshot for when we review the file

Once we've got our declared functions, we then pass them into our IIFE which acts as a main function. When you run this code, you get each entire page in under a second. For the sake of brevity, I'm only going to show the first and last screenshot.

First Screenshot quotes-1

Final Screenshot quotes-10

Conclusion

Both Declarative functions and IIFEs have their place in JavaScript. While you might not prefer to use IIFEs (I still don't), you at least understand how and why they're used. You also got a crash course in web scraping!!! If you'd like to know more about Puppeteer, you can check out their docs here.

More Cool Articles from Chifi

Here at Chifi, you can learn a ton of cool stuff. If you're in the mood to binge read, take a look at one of the articles below!

Also, I've recently launched my own YouTube Channel with coding tutorials, tech interviews and more stuff to come! Check out CodeAndCrypto. I'm always looking for interesting people to interview as well. If you'd like to be featured on the channel, feel free to drop a comment below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment