Anonymous functions and variables

How a function is assigned to a variable? What is the point of that if we are going to call it anyway?
I also want to understand the meaning of arrow functions? Can anyone explain its parts? The only difference is the function keyword and the arrow, is it some kind of shortcut?

Challenge: Use Arrow Functions to Write Concise Anonymous Functions

Link to the challenge:

One use for this is if you call a function that returns a function, then you can save the returned function in a variable and call it at a later time using that variable.

The Difference Between Regular Functions and Arrow Functions

can you give an example, please?

Here is a simple example, hope this helps

const myFunc = () => {
  console.log("hello")
}

const myInterval = setInterval(myFunc, 1000);

// set interval is stored inside a variable so we can clear it

// you can write it like this

// setTimeout(() => clearInterval(myInterval), 3000);

// or store the function to clear interval in a variable to be called later

const clearMyInterval = () => clearInterval(myInterval)

setTimeout(clearMyInterval, 3000);

I’m not quite sure what you are looking for? There were plenty of examples on the doc I linked you to. Perhaps it would be better if you asked a very detailed question about what you don’t understand instead of me trying to guess.

Can you provide an example of what you mean by this?

And to echo what bbsmooth is saying, please provide your own examples rather than have us try to guess what is confusing you.

I did not quite understand what you meant by this, so I wanted an example.

One use for this is if you call a function that returns a function, then you can save the returned function in a variable and call it at a later time using that variable.

You’re putting a lot of responsibility for your learning on other people. Asking lots of questions is good, but you need to work with us to narrow down specific things that you don’t understand. Broad questions get broad answers.

1 Like

Sorry for that, I’ll work on it.

This MDN article on closures provides several examples of returning functions and saving them off in variables for later use.

1 Like

Not sure I understand the question so this is probably not the answer you were looking for.

But you can’t really call a function if it has no identifier. Unless you immediately invoke it I guess.

(() => console.log('Called'))();

Arrow functions are anonymous function expressions but the function definition is still stored inside an identifier (variable name).

Summary
// anonymous function expresstions
const anonymousFnExp = function () {
  console.log('Called')
}
// anonymous function expresstions
const anonymousFnExp = () => {
  console.log('Called')
}

You can also create a named function expression. The name is available inside the function body (local only to the function body). You can use the name for recursion for example. Here is an example from MDN.

I believe there was a time when the name was needed for the stack trace to show the name of the function that was called but as far as I know most runtimes now will print the variable name the anonymous function was assigned to.

Summary
const namedFnExp = function() {
  const fn2 = function() {
    const fn3 = function() {
      console.lag('No not that')
    }
    fn3()
  }
  fn2()
}

namedFnExp();
/*
VM135:4 Uncaught TypeError: console.lag is not a function
    at fn3 (<anonymous>:4:15)
    at fn2 (<anonymous>:6:5)
    at namedFnExp (<anonymous>:8:3)
    at <anonymous>:11:1
*/

As opposed to this.

Summary
(function () {
 (function () {
   (function () {
     console.lag('test');
    })();
  })();
})();

/*
VM149:4 Uncaught TypeError: console.lag is not a function
    at <anonymous>:4:14
    at <anonymous>:5:7
    at <anonymous>:6:5
    at <anonymous>:7:3
*/

1 Like

An important point to understand is that the way you and i see things doesn’t always exactly match the way javascript sees them.

Where you and i might see a number, javascript sees a primitive data value of type "number", which only means it can be wrapped at need with javascript’s Number object in order to give it additional behaviors (like 42.0835375.toFixed(3) - the number itself doesn’t have any methods, but as a Number it gains functionality).

In the same way, where you and i see a function, javascript sees a non-primitive object, just data, but with the type of "function". So there are two key points to get here:

  • first, that our function (whether a “fat arrow” or traditional) gains some functionality from the Function wrapper when and if we need, and
  • second, that our function is just another form of data, as far as javascript knows.

Functions are just data. They can be placed in variables, passed as arguments or return values, and in most ways treated as data.

When we do this:

function sayBooTo(name){
  return `Hey ${name}, I'm a spooky ghost! Boo!!`
}

// what javascript is actually doing...
var sayBooTo = function sayBooTo(name){
  return `Hey ${name}, I'm a spooky ghost! Boo!!`
}

// which is functionally the same as
const sayBooTo = (name) => `Hey ${name}, I'm a spooky ghost! Boo!!`

When we write a named function expression (like the first line), javascript creates a var declaration automatically. When we assign the function to a variable ourselves (or use an anonymous function assigned to a variable, like the third), we are doing much the same directly.

I prefer to explicitly declare my variables, though, as i like my functions to be const-ed.

1 Like

Thanks for the explanation. I was thinking of functions like an if statement or a loop.

If statements… for making decisions
Loops… for iteration
Functions… for reusable code

As far as I know we cannot write:

Var something = if (condition){execute something}

So I assumed we cannot do that for functions too.

I’m not sure what you are expecting the variable something to equal if you could do this?

But you could do something similar with the ternary operator:

const something = condition ? func() : 0;

You could even use an IIFE:

const test1 = condition ? (function() { return 10; })() : 0;

2 Likes

Ah, ok. That gives more context.

statements do something. You can’t assign statements to variables or return statements from functions because that doesn’t make any sense – a variable holds a value, a function returns a value (even if that value is just undefined).

expressions are something. You can assign expressions to variables and you can return expressions from functions because they’re a value.

Functions are expressions, by definition. They always produce a value.

Loops are statements, they don’t produce a value, so it makes no sense to assign them to a variable. Same with conditional statements: var something = if (condition){execute something} doesn’t make sense.

2 Likes

This, i think, might be the source of the confusion. We declare functions, like this:

const goBoom = () => alert("BOOOOOMMMM!!)

And now goBoom is that function. But the function is purely data. We can pass that function or store it as we like, referenced by goBoom.

But goBoom() is different - it is the function expression. It is the point at which we execute the function, using the data in that variable to evaluate something, and to return some value from that evaluation.

But you’re right, assigning if(something){ blah() } to a variable makes no sense. We can use if to decide what to assign to a variable, but we can’t assign the if itself to a variable.

if is a keyword, as is for. We can’t assign keywords to variables. And function is also a keyword. We don’t assign function to a variable, we assign the data we declare using the keyword.

1 Like

Ah, yeah @snowmonkey has been a bit clearer there. And I should have been a bit more specific: an expression is something that evaluates to a value.

This does not evaluate to a value in JS:

if (condition)  {
  // something
}

condition evaluates to a value, it’s an expression. Whatever something is might also be an expression. But the if () {}, the actual statement itself? That doesn’t ever evaluate to a value. Same with loops. Same with variable declarations themselves (not what is assigned to them).

An if statement is [almost] saying “if this expression evaluates to true, go to this line in the code, otherwise go to this line”. A loop may be saying “go to this line of code over and over again”. It’s an instruction (as I said “do something” rather than “is something”).

functions are not like that. They’re a little machine that you can use in your program. You declare the function, then you can call it in your code as many times and in as many places as you want. And they resolve to a concrete value. They are “do something”, but a. the declaration, when evaluated is a reference to a concrete object and b. when they’re executed, they evaluate to a concrete value.

Note that it is a design decision to have conditional/loop statements rather than conditional/loop expressions. It’s not something set in stone in computer science or anything, JavaScript just happens to differentiate between them, copying off several other popular languages. In contrast, in other languages these things are expressions. For example, Rust:

fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    assert_eq!(result, 20);
}

Regarding “why would I need to assign a function to a variable”, well, that’s what you’re doing here:

function example () {
  // do something
}

There’s a function assigned to an identifier called example.

Practically speaking, this is basically the same (there are very slight differences, but practically):

const example = function () {
  // Do something
}

As is this:

const example = () => {
  // Do something
}

There are slight (albeit important) differences to do with scope for arrow functions vs. function functions, but for the most part, going to be the same.

The most common use for anonymous functions is as callbacks:

[1,2,3].map((n) => n * 2)

And generally you are correct in saying that it’s a kind of shortcut. It makes sense from a developer point of view to have a shorthand for the most common usecase, meaning you don’t need to write this:

[1,2,3].map(function (n) {
  return n * 2;
})

But anyway, as I say, there are actual important differences to do with scope, but in many (the majority of?) cases they are, practically speaking, used as shorthand.

The important differences – this goes back to what’s been said: it’s far easier to give explanations when you have specific examples, abstract explanations aren’t likely to be helpful until you encounter the concrete problem they relate to

1 Like