Why this logs 1 ? It's confusing to me , can anyone please explain?
(function(){
var hello = () => {
console.log(1);
}
function hello () {
console.log(2);
}
return hello()
})()
Why this logs 1 ? It's confusing to me , can anyone please explain?
(function(){
var hello = () => {
console.log(1);
}
function hello () {
console.log(2);
}
return hello()
})()
Function declarations (statements that start with function functionName(
)get hoisted to the top of their enclosing scope, and assign to their function name identifier first, before anything else runs in that scope.. Assignments with =
do not.
The fact that it's an arrow function doesn't particularly matter - a function
assignment at the same point would produce the same results.
(function(){
var hello = function() {
console.log(1);
}
function hello () {
console.log(2);
}
return hello()
})()
Your code is equivalent to
(function(){
// hello identifier gets created at the very beginning
var hello;
// hoisted function declaration assigns to `hello`:
hello = function hello () {
console.log(2);
}
// assignment with =, not hoisted, assigns to `hello`
hello = () => {
console.log(1);
}
return hello()
})()
I'd recommend using ES2015+ syntax at least, which will help prevent you from making these sorts of accidents - it will forbid re-declarations of variables if you use let
or const
.
(function(){
let hello = () => {
console.log(1);
}
function hello () {
console.log(2);
}
return hello()
})()
Because:
var
declarations dovar
declaration for a binding that already exists is not an errorSo your code is creating a binding, assigning a the declared function to it, then overwriting that value with the arrow function. In effect:
(function(){
// Declaration of the var-scoped binding happens first
var hello;
// Then the function declaration is processed, assigning
// the function to the binding
hello = function hello() {
console.log(2);
};
// Then the step-by-step code begins and processes
// the assignment
hello = () => {
console.log(1);
};
return hello();
})();
Side note: var
is effectively deprecated, there's no reason to use it in modern code. Instead, use let
or const
. They have more rational behavior:
let
or const
declaration that would conflict with a var
-style declaration like a function declaration)var
scope, and they don't create properties on the global objectYour example would have given you a nice, useful error with let
or const
:
(function(){
let hello = () => {
console.log(1);
};
function hello () {
console.log(2);
}
return hello();
})()