What is the difference between a named function expression and a function declaration?

Viewed 111
  1. var a = function b() {
        b = 123;
        console.log(b === window.a)  // true
        console.log(b)    // function b() { ... }
    }
  2. function a() {
       a = 3;
       console.log(a)    // 3
    }

Why is the variable b not changeable, what is it?

1 Answers

There are two types of locals in Javascript. These are

  • Declared locals: When you declare a local variable by using one of the keywords (e.g. var, const, let), these variables are determined as declared. In non-strict mode, your variable declaration falls back to var.
  • Artificial locals: When you declare a function using the function declaration syntax, you actually declare an artificial local with the name of the function. For example, function foo() {} defines an artificial local named foo.

JavaScript handles these two types of locals differently in terms of variable hoisting. Declared locals need to be reached to the declaration (or their first usage) to be referenced. On the other hand, artificial locals are hoisted to the initial scope state, hence it is usable from the start of the scope.

You may consider this code:

bar();      // prints 'bar' on the console
foo();      // error: 'undefined' is not callable

const foo = function () {
  console.log('foo');
}

function bar() {
  console.log('bar')
}

bar();      // prints 'bar' on the console
foo();      // prints 'foo' on the console

In your example, your a = 3 statements mutate declared local in the outer scope, overriding your old artificial local declared as a side-effect of your function declaration. Since you are using non-strict mode, it is pretty hard to see the difference, however, you may think about your implementations like so:

var a_dec = function b_art () {
  b_dec = 123;
  console.log(b_art === window.a_dec);
  console.log(b_art);
}

function a_art () {
  a_dec = 3;
  console.log(a_dec);

  // when you run this, b_art is not reachable with a_dec anymore
}

This is an implementation detail. Here, the artificial variable declaring the function takes precedence over the declared local. The a is declared as a declared variable for the first time, so it is counted as it is. The matter of being a declared variable makes it mutable, in contrast to the artificial variables.

Related