strange behaviour in function Hoisting - javascript

I written below script and executed in scratch pad.
baz();
var baz = function(){
console.log("Hello World");
}
When I try to execute above script, I got below kind of exception. I know, this expression comes because, hoisting is not valid for function expressions.
/*
Exception: TypeError: baz is not a function
#Scratchpad/1:1:1
*/
Now, I replaced the function name 'baz' with 'say_hello', and re run the application, it is working fine with no exception. Is there any reason for this behaviour?
say_hello();
var say_hello = function(){
console.log("Hello World");
}

say_hello();
function say_hello(){
console.log("Hello World");
}
This is the one which is really working fine with no exception
The reason is:
JavaScript only hoists declarations (variable and function declarations), not initializations
If a variable is declared and initialized after using it, the value will be undefined. For example:
console.log(num); // Returns undefined
var num;
num = 6;
If you declare the variable after it is used, but initialize it beforehand, it will return the value:
num = 6;
console.log(num); // returns 6
var num;
For more information:Only Declarations Are Hoisted

Related

Why I cannot access this variable inside this simple function?

Im new to Javascript and I dont understand whats happening how the scope works in the following codes:
//Code n°1:
let num = 1;
function test(){
console.log(num);
}
test() //As I expected I get in console "1"
//Code n°2:
let num = 1;
function test(){
let num = 2;
console.log(num);
}
test() //As I expected I get in console "2"
But here is the problem:
//Code n°3:
let num = 1;
function test(){
console.log(num)
let num = 2;
console.log(num);
}
test() //I expected to get in console "1" and then "2" but instead I get an error.
When I run in my browser the code n° 3 Im getting this error:
Uncaught ReferenceError: can't access lexical declaration 'num' before initialization
If I look at code 1 and 2 I suppose that after running code 3 I will get in my console the number 1 and then number 2. But that isnt happening. Why?
Thank you so much!
The JavaScript exception "can't access lexical declaration `variable' before initialization" occurs when a lexical variable was accessed before it was initialized. This happens within any block statement, when let or const declarations are accessed before they are defined.
When the 'test function' is called, the function body gets executed. When it reaches to 'console.log(num)', it starts to search for the 'num variable declaration' (or 'num assignment' or 'num reassignment) in the test function scope. So it finds the variable declaration in the next line. The priority for searching for a variable is:
Current Scope
Closure
Scope Chain
So, when the variable declaration is found i the current scope, searching is not continued to scope chain. (It will not search for num variable in global scope.)
I guess this is the reason of the error, but as I am new to javaScript, I am not completely sure.
If you initialize the variable without redeclaring, it will work normally, now if you redeclar the variable, then this error will happen with let or var, because in the same scope, it is being called by the previous console.log().
It is not recommended that you re-declare let variables, if you need to, don't use the same in previous statement, note that if you comment on the first console.log(), the code will work again, this occurs exactly for the lifetime of the variable within this scope, in this case, let
let num = 1;
function test(){
console.log(num)
let num = 2;
console.log(num);
}
test()
Bacause in javascript functions and variables declared with var are hoisted, moved up to the top of the function/lexical block.
But let keyword respect the lexical flow. It pins variable where it is declared.
console.log try to access a variable that is declared bellow in the flow.
So move up manually your let declaration to be above de console.log or change it to var let num = 2; to let javascript engine move it above all automatically.
var num = 1;
function test(){
let num = 2;
console.log(num);
}
test()
or
var num = 1;
function test(){
console.log(num)
var num = 2;
console.log(num);
}
test()
or, to get access to global var num, which is shadowed by declarations from test's body, var or let, no matter
var num = 1;
function test(){
console.log(num)
//let num = 2;
console.log(num);
}
test()

JS hoisting functions. ( Why does this code snippet work? )

The following code snippet shows a basic object that contains a variable str, a member variable hello, and a member function test. I thought I knew JS pretty well and expected this code to fail because the test function would be hoisted to the top and would be unable to access the str or vm variable. I was then surprised to see that this actually works. Why does this code function? Does hoisting still occur?
function SomeObject( ) {
var vm = this;
vm.hello = "hello";
vm.test = test;
var str = "testig!";
function test() {
console.log( vm.hello );
console.log( str );
}
}
var s = new SomeObject();
s.test();
Output:
hello
testig!
Due to hoisting, you essentially end up with this:
function SomeObject() {
var vm;
var str;
var test;
test = function test() {
console.log(vm.hello);
console.log(str); // Works because we haven't run the function yet
}
vm = this;
vm.hello = 'hello';
vm.test = test;
str = 'testig'; // str now has a value, function hasn't been called yet
}
var s = new SomeObject();
s.test(); // Function is called after str has been given a value
All declarations are hoisted to the top of their enclosing scope container.
A function declaration, such as:
function foo(){ }
Will be hoisted to the top of its enclosing scope, so it may be called by code that is written BEFORE the function is.
Variable declarations are hoisted as well. So, code such as:
var x = 10;
Will experience hoisting as well. BUT, only declarations are hoisted, so in the previous example, only
var x
is hoisted. The x = 10 assignment won't happen until the actual code location is reached.
Similarly, function expressions work the same way. With this code:
var f = function() {};
Only the var f is hoisted, not the assignment. If you were to try to call f before the actual code location were reached, you would receive an error indicating that f is not a function.
Your code works simply because when you call:
var s = new SomeObject();
The function test is not executed, but all the variable assignments are. So, when the time comes for this:
s.test();
All the variables and the function are ready to go.

JAVASCRIPT functions knowing about other functions

Is javascript code read from the top down?
In other words if I have:
function Color(){
}
function Weather() {
}
If I wanted to incorporate some type of weather object inside the Color function would it be possible since Weather is defined afterwards?
The function Color won't know about Weather as it's being parsed, but it will once it is called. For example:
// Since variable declarations are hoisted to the top,
// myVar will be undefined (same as simply saying "var myVar;")
console.log(myVar); // <-- undefined
var myVar = 5;
console.log(myVar); // <-- 5
// test2 hasn't been defined yet, but it doesn't matter
// because test isn't being executed
var test = function() {
test2();
}
// This will throw an error: undefined is not a function
// because test2 isn't defined
test();
var test2 = function() {
alert("test2");
}
// This won't throw an error
test();
Essentially, you should execute after all functions have been defined. However, if you use the function functName() {} syntax, then it is hoisted just like a var statement.
function test() {
test2();
}
// Works!
test();
function test2() { alert("test2"); }
JavaScript is parsed "top-down" and Function Declarations are hoisted constructs - see var functionName = function() {} vs function functionName() {}. Parsing happens before the JavaScript execution itself starts; the following thus covers the evaluation semantics1.
Given the effect of function hoisting, the following code is valid, although it seems like it might not be:
function a(){
return b();
}
alert(a()); // alerts "b", even though "b comes later"
// This declaration IS hoisted
function b() {
return "b";
}
However, considering that even when using "var fn = .." (when the assignment is not hoisted) the ordering usually doesn't matter because the evaluation of the assignments happens before the usage:
var a = function () {
return b();
}
// alert(a()); <- this would fail, because b is not assigned yet
// This assignment is NOT hoisted
var b = function () {
return "b";
}
// But b is assigned before here, meaning that the order of the constructor
// functions still Just Doesn't Matter.
alert(a());
As such, in the case where there are two constructor functions (e.g. Color and Weather) which are [mutually] dependent, it doesn't matter where they are located in the same scope relative to each other.
1The thing that matters is the expression representing the dependency is resolvable when evaluated (which is relative to the evaluation code, but not related to the parsing/placement order of the functions).
so basically yeah you can implement something to a function that appears in a previous code.
hole this helps you understand it better.
var weather = function() {
if (weather === red) {
console.log("weather is represented by the color red");
}
else {
console.log("Not the right color");
}
};
weather(red);

Why can JavaScript functions to be accessed Before they are defined? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can I use a function before it's defined in Javascript?
As would be expected, the following code throws an error because Foo is not defined:
window.Foo = Foo;
Also as expected, this throws the same error:
window.Foo = Foo;
Foo = function() {
...
};
Curiously, this works just fine:
window.Foo = Foo;
function Foo(){
...
};
How is this possible? Isn't JavaScript interpreted line-by-line?
Hoisting is only part of the story here.
First, to explain hoisting:
When you use var in a JavaScript program, you declare a variable. Wherever that variable is declared in a JS scope, it is hoisted to the top of that scope. JavaScript has only Global or Function scope; in the case of a function
function hoistAway() {
console.log(a);
var a = 5;
}
is equivalent to
function hoistAway() {
var a;
console.log(a);
a = 5;
}
As you can see, the declaration is hoisted, but the initialization is not. Thus, this code would log undefined on the console, rather than 5. However, it would be satisfied that a exists.
When you don't use var, the declaration is not explicit, so it doesn't get hoisted. Thus:
function hoistAway() {
console.log(a);
a = 5;
}
will result in an error message.
In your examples:
window.Foo = Foo;
Foo was never declared, so you get an error.
window.Foo = Foo;
Foo = function() {
...
};
Again, Foo was not declared, so no hoisting. For the record:
window.Foo = Foo;
var Foo = function() {
...
};
will not throw an error. However, only the declaration is hoisted, so if you did something like
var bob = {};
bob.Foo = Foo;
var Foo = function() {
...
};
then bob.Foo would be undefined. The special case of window.Foo = Foo is weird because Foo and window.Foo are the same in the Global scope.
Finally:
window.Foo = Foo;
function Foo(){
...
};
works, because function declarations (as opposed to function expressions) are also hoisted; both the name and the definition gets hoisted, so this would work as intended.
The script is parsed first, allowing your code to call functions that are defined later on.

Javascript variable declarations at the head of a function

I've been told that javascript variables should all come before they are used in a function, such that:
function contrived() {
var myA, myB;
myA = 10;
myB = 20;
return myA + myB;
}
Is prefered over:
function furtherContrivance() {
var myA = 10;
var myB = 20;
return myA + myB;
}
Is this the case? And why is that?
I guess some people might prefer the former style because that's how it works inside. All local variables exist for the entire lifetime of the function, even if you use var to declare them in the middle of the function.
There's nothing wrong with declaring variables later in the function, syntax-wise, it might just be confusing as the variables will then exist before the line that declares them. Hence this function:
function bar() {
alert(foo); // Alerts "undefined". Not an error because the variable does exist.
var foo = 10;
alert(foo); // Alerts the value 10.
}
Is equivalent to this:
function bar() {
var foo;
alert(foo);
foo = 10;
alert(foo);
}
Another related fact is that nested function definitions (done using function foo() { ... }) will get moved to the top of the containing function as well, so they will be available even if the code that calls them comes before them.
Yes, the variable declaration should come at the top of the function:
function foo() {
var a, b;
}
However, initializing variables can be part of the declaration:
function foo() {
var a = 10, b = 20;
}
The reasoning behind declaring all variables at the top of the function where they are used is to avoid scope confusion.
Here is an example of bad code:
function foo() {
var b;
for (var i = 0; i < 5; i++) {
var a;
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
If you execute the code, it will log 4, 4 5 times, rather than counting up. This is because only functions act as closures and introduce new scope. In JavaScript, any var declaration within a function gets executed at the beginning of the function.
This makes the above error much more visible:
function foo() {
var a, b, i;
for (i = 0; i < 5; i++) {
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
There is no difference in this case between this two. I'd go with:
function furtherContrivance() {
var myA = 10,
myB = 20;
return myA + myB;
}
which is knows as single var pattern in javascript.
What you really need to take care of is defining your variables in the beginning of your functions. There is a thing in javascript called variables hoisting which means that variable definitions used in function "raise" on top. It's best described by an example:
var x = 'global'; // global (bounded to a global object which is window in browsers)
function func() {
alert(x); // undefined (you expected 'global', right?)
var x = 'local';
alert(x); // local
}
func();
what really happens is called (as I said) variables hoisting (definition of x raises on top), so the code above is actually the same as:
var x = 'global';
function func() {
var x; // definition of `x` raised on top (variables hoisting)
alert(x); // undefined in a local scope
x = 'local';
alert(x);
}
What a javscript interpreter does is it looks inside a function, gathers locally defined variables and raises them on top - this might be a good reason why you should use single var pattern.
In the example you give this is absolutely not the case. In a language like Javascript, it will be more of a developer preference, but it won't have any impact on the result.
Yes, place them at the top. It adds to code clarity.
Try this example:
var x = 1;
(function() {
x++;
alert( x ); // What will this alert show?
var x = 'done';
alert( x );
})();
Looks like it should alert 2, but it alerts NaN.
This is because the variable declaration is hoisted to the top, but the initialization stays in the same place.
So what is actually happening is:
var x = 1;
(function() {
var x;
x++;
alert( x ); // What will this alert show? NaN
x = 'done';
alert( x );
})();
...which makes the NaN expected.
For readability, it's definitely preferred.
However, Javascript "hoists" declarations. Hoisting means that vars and functions will be automatically moved to the top of their scope. This allows you to do things such as use a function before it's declared:
function myScope()
{
test();
function test()
{
//...
}
}
This can lead to some confusion, especially if variables within block scopes are declared. For example:
for(var i in foo)
{
var e = myFunc();
}
The declaration of e will be hoisted to the top of the closure, and e will be initialized to undefined. This allows for some interesting non-intuitive situations, such as:
if(!foo) //Will not throw reference error because foo is declared already
{
var foo = {};
}
So, regardless of how you declare your variables, they'll all get "moved up" to the top of the function anyway.
Hope this helps!

Categories