let greeting = "hi"
outside(greeting)
let outside = function(x){
document.getElementById("myH1").innerHTML = x
}
let inside = function(x){console.log(x)}
It says in console: Cannot access ‘outside’ before initialization
at functionexpression.js:23:1
(anonymous) @ functionexpression.js:23
The error tells you what the issue is. You have to define the function before you can use it. Just moving the call to outside will make it work.
let greeting = "hi"
let outside = function(x){
document.getElementById("myH1").innerHTML = x
}
outside(greeting);
Javascript is not a compiled language, so things work from top down. Things must be defined (meaning they have to be higher in the document) before they can be used
Getting a bit deeper into the topic, the issue of vertical ordering of the lines exists when using let and const, because they help us to write better code.
When using older techniques such as var, or a function declaration, those are pre-processed before the code is run, so when using those the order was of less importance. But still, even when using those it’s important to program defensively, and ensure that things are defined first before you attempt to use them.
Function declarations are hoisted like variables. Unlike variables (vars) which are hoisted to the top and given a value of undefined in the case of function declarations the entire definition is hoisted to the top.
This is why you can call or invoke the function ahead of it’s position in code
Try and picture hoisting as variables being put into an object connected to the code. When we want these variables or function declarations that is where javascript is going to look.
Consider the following:
1. const x = 2
2. var y = 5
3. let z = 10
4. function log(val) {
5. console.log(val)
6. }
When we execute line 1 --> 1. const x = 2 the variable object looks a bit like this.
// variable object
{
x: 2,
y: undefined
z:
log: function(val) { // whole function has been put here from the get go.
console.log(val)
}
}
When thinking about it, function declarations are side effects. Procedural Programming is highly dependent on order of execution to avoid possible side effects. Since function declarations hoists to the top of the execution context, it can possibly change the program meaning if the order is changed.
Hm… not sure about that, they are local to the current scope as any variable declarations after all. Compare this to PHP, where (for reasons I fail to comprehend) function declarations certainly are side effects:
function foo() {
function bar() {
echo 'bar';
}
echo 'foo';
}
// This would throw a fatal error:
// Call to undefined function bar()
bar();
foo();
// However, this would actually work
// and echo "foobar"
foo();
bar();
The JS equivalent OTOH would have to be explicit about global definitions:
function foo () {
function bar () {
console.log('bar')
}
globalThis.bar = bar
console.log('foo')
}
// ReferenceError: bar is not defined
bar()
foo()
// Logs "foo\nbar"
foo()
bar()