Functions vs Function Expressions

Hello everyone, does anyone know the difference between functions

function x() {

};

and function expressions?

const x = function() {

};

What are the differences? And which one should be used?
Thanks!

Function declarations
Function expressions

This is not a function expression…

variableName(argument1, argument2)

It is akin to,

function variableName(argument1, argument2) {

}

This is a function expression…

variableName = function(argument1, argument2) {

}

Only declared functions are hoisted. Hoisting doesn’t really protect anything so is rather moot. We can still overwrite either of the above with,

variableName = null

Poof! They’re gone.

The new keyword, const makes it possible to define functions that are not so vulnerable.

const func = function() {
    
}
func = null
Uncaught TypeError: Assignment to constant variable.

Bottom line, the anonymous function expression declared with const creates a permanent binding, and protects the integrity of our functions.

2 Likes
Foo = x => {
    this.x = x;
}
foo = new Foo('foo')
Uncaught TypeError: Foo is not a constructor

In ES5, all functions are constructors. Arrow functions, once introduced, did not come with that capability. this won’t work; these functions do not operate on a context other than themselves.

ab = (a, b) => a * b

can be readily expressed as,

console.log(ab(6, 7))

It’s still a form of constructor, but it is its own instance, and it has no methods. It is just the syntax to write perfect function expressions.

I’m not truly convinced about the new class architecture. We know that we can protect a constructor function with const, but how do we protect a class?

class Foo {
    
}
foo = new Foo()
foo instanceof Foo
true
Foo = null
foo instanceof Foo
Uncaught TypeError: Right-hand side of 'instanceof' is not an object

As fancy as class is, it is no match to a const defined constructor function.

{
    const Foo = function (m, n) {
        this.m = m;
        this.n = n;
    }
    foo = new Foo(6, 7)
    Foo.prototype.ab = function () {
        return this.m * this.n;
    }
    foo.ab()
}
42

There is some vulnerability if the instance variables are known. Above we gave the constructor a new method, without objection.

1 Like

Here’s another explanation about using a func expression vs. a func declaration:

They’re actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.

Function declarations load before any code is executed.

Function expressions load only when the interpreter reaches that line of code.

So if you try to call a function expression before it’s loaded, you’ll get an error! If you call a function declaration instead, it’ll always work, because no code can be called until all declarations are loaded.

https://stackoverflow.com/questions/1013385/what-is-the-difference-between-a-function-expression-vs-declaration-in-javascrip

Hoisting is not a magic pill and is rather moot, these days. It doesn’t offer any advantages apart from where we write the call relative to where the function is defined. Even decades ago best practice was to write functions at the top of a script and references (and/or listeners) below that. Note how above it was so easy to overwrite function declarations.