5

I need some confirmations on what’s happening behind the screen.

There’s an article in MDN that said that we shouldn’t declare functions in a block-level, such as, inside an if-statement. Because it’s inconsistent throughout browsers and anything to do with pre-ES2015 (or pre-ES6).

The function inside the if-statement will not be created unless the condition is true.

I was wondering, IF the condition is true, let’s say 5 minutes later after JavaScript is loaded and set synchronously, will it create the function? Does it still have memory of the code in order to create the function, or is it dumped in unused code and all?

I would like to know whether the function still exists even after the if-statement is completed. Is it accessible? How long is it accessible? Is it accessible until the if-condition is false? Does the result differ from ES6 and pre-ES6? I’ve heard there’s no scope pre-ES6 in if-statements.

e.g.

if (condition) { function foo() {console.log(“hello world”); } }

I was confused after reading an article in MDN on ‘Functions’ under ‘block-level functions in non-strict code’: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

Ooie
  • 51
  • 3
  • 1
    See https://stackoverflow.com/questions/60416842/does-this-safari-behavior-break-the-ecmascript-specification for example of inconsistency. – QuentinUK Feb 29 '20 at 07:29
  • 4
    Javascript is single threaded, code is evaluated when it is executed, not before or after. Just **do not** declare functions inside if blocks as behaviour is not consistent. If you must conditionally create functions, use function expressions. – RobG Feb 29 '20 at 07:38
  • https://stackoverflow.com/a/31461615 - seems to answer the relevant primary questions. Don’t know why I had to read through an essay to get it.. – user2864740 Mar 01 '20 at 01:08

1 Answers1

0

IF the condition is true, let’s say 5 minutes later after JavaScript is loaded and set synchronously, will it create the function?

The function will be created as soon as the if runs, immediately.

Does it still have memory of the code in order to create the function, or is it dumped in unused code and all?

I would like to know whether the function still exists even after the if-statement is completed. Is it accessible? How long is it accessible?

This behavior will be the same regardless of if the function is declared in an if block or not: if nothing can possibly reference the function in the future (for example, if the block ends and nothing inside the block has a reference to the function), it will eventually be garbage collected. The function may still "exist" in memory for a time until the GC runs.

For example, it should be clear that the following function should always continue to exist, at least until you reload the page:

// IIFE, to get off the top level
(() => {
  if (true) {
    function foo() {
      console.log('clicked');
    }
    window.addEventListener('click', foo);
  }
})();

This is because the addEventListener has been passed a reference to the function.

But the following foo function will get GC'd (maybe a second or few after the page is loaded - it depends on the underlying engine, and isn't visible to Javascript):

// IIFE, to get off the top level
(() => {
  if (true) {
    function foo() {
      console.log('clicked');
    }
  }
})();

If nothing has saved a reference to the function by the time the block that scopes the variable has finished, the function will not be accessible anywhere, and will be GCd.

The rest of the question looks to be essentially the same as: "where can the function be referenced", which is best described in Bergi's answer here. It's a bit complicated, and the behavior differs depending on whether you're using strict mode, the ES version of the environment, and the environment itself (implementations do not always conform to the specification).

For predictable, easy-to-read code, probably best to simply never use function declarations in non-function blocks; only use function declarations when directly inside function blocks.

(Note that function expressions, where the function is used as a value and passed to something or immediately invoked or explicitly assigned to a variable, are not the same as function declarations - function expressions are fine, it's just the weird behavior of function declarations that's problematic. Also note, per comment, that a "function declaration" is sometimes called "function statement".)

Community
  • 1
  • 1
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • 1
    Functions **statements** appearing *inside if-blocks* is the issue. Function **expressions** are OK. So the other stuff is nice, *but it doesn’t really matter* because the fundamental concept is ill-defined/inconsistent behavior across implementations. – user2864740 Mar 01 '20 at 00:57
  • If this changed from ES3/5/6, etc, then that should be specifically addressed, as the OP requested. – user2864740 Mar 01 '20 at 01:03
  • 1
    I did already say *never use function declarations in non-function blocks; only use function declarations when directly inside function blocks.* Function expressions are, of course, completely different, since they're expressions, rather than weird kinda sometimes-hoisted things – CertainPerformance Mar 01 '20 at 01:53
  • If you're confused about the wording, what I called a "function declaration" sounds like the same thing that you're referring to by "function statement" - they're both the `function fnName() { ...` constructs not connected to any other expression – CertainPerformance Mar 01 '20 at 01:56