0

I have the following IIFE (Immediately Invoked Function Expression):

(async () => {
  const brwSettings = await brwApi.get(
    ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce  
  );
  settingsDataAvailable(brwSettings);
})();

Below this IIFE, I declare the settingsDataAvailable function like this:

const settingsDataAvailable = (data) => {
  console(data);
};

And this is working fine.

However, if I call settingsDataAvailable outside of the IIFE, it gives me the error Uncaught ReferenceError: Cannot access 'settingsDataAvailable' before initialization.

(async () => {
  const brwSettings = await brwApi.get(
    ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce
  );
})();
settingsDataAvailable(brwSettings); // throws an error

const settingsDataAvailable = (data) => {
  console(data);
};

Why does this throw an error but the code snippet earlier did not?

dayuloli
  • 16,205
  • 16
  • 71
  • 126
RowanBlub
  • 21
  • 3
  • 2
    Because in the first example, the access happens after the definition (time-wise! not in terms of where they are located in the code) while in the second example it happens before. (Additionally, the second example would run into the issue that also `brwSettings` is not only not existing yet but also not even in scope.) – CherryDT Jan 17 '23 at 18:45
  • The earlier code doesn't run until the `brwApi.get()` call completes. By that time, the symbol (the function declared in the `const` statement) is initialized. – Pointy Jan 17 '23 at 18:46
  • In the first example, invocation of `settingsDataAvailable(...)` occurs at minimum one microtask later due to the presence of an `await`. This means that the synchronous top-level evaluation of the entire script will have completed before that invocation is reached. In your second example you are merely attempting to synchronously reference an identifier inside its temporal dead zone. – Ben Aston Jan 17 '23 at 18:49

1 Answers1

0

In this part:

  (async () => {
    const brwSettings = await brwApi.get(
      ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce
    );
  })();
  settingsDataAvailable(brwSettings);

variable brewSettings is in function scope, it means that all code out of it don't know anything about variables declared in this function, but you should know that all code inside function know all variables, which are in it. This will work:

  (async () => {
    const brwSettings = await brwApi.get(
      ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce
    );
    settingsDataAvailable(brwSettings);
  })();

And this:

  (async () => {
    const brwSettings = await brwApi.get(
      ajax_var.resturl + "?_wpnonce=" + ajax_var.restnonce
    );
    const doSome = () => {
      settingsDataAvailable(brwSettings);
    }
    doSome()
  })();

About top part of your question I don't shure, but it seems like compile feature. I know exactly that let and const don't have hoisting mechanism in js. So, they can't be accessed before initialization, only function declaration like function foo() {} has this mechanism.

For more information about scopes I recommends very popular book "You don't know js".