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

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.

Related

Weird behavior of if(true) on JavaScript scope..?

So I was testing scope of JavsScript (var, let, and const), and I found a weird behavior that I couldn't really understand.
var write = document.getElementById('demo');
function test() {
var m = 'hello';
}
test();
write.innerHTML = m;
//This doesn't work
In above case, JS cannot accesses var m declared locally from global scope.
var write = document.getElementById('demo');
if(true) {
var m = 'hello';
}
write.innerHTML = m;
//This works
In above case, JS accesses var m declared locally from global scope.
Can someone explain why that is..?
It is because of Hoisting. Also var has function level scope
var write = document.getElementById('demo');
var m; // m will be undefined here, declared but not initialized
if (true) {
m = 'hello'; // m is initialized her
}
write.innerHTML = m;
<div id='demo'></div>
In the first case, var declaration is scoped at function level and thus its limited to function test
In the second case, if scope is block scope and hence var declaration escapes into the global scope due to Hoisting
Thus in the first case you can't use m outside function test but you can do so in the second case.

Way to understand this code. How is it working?

I was exploring scopes in javascript and came to know this problem. I don't understand how this problem is working.
function checkType() {
return foo;
foo = 10;
function foo() {};
var foo = 11;
};
console.log(typeof checkType())
My question is this how does javascript compiler decide to return function not variable. Any reference or explanation are welcome.
This is how the compiler will compile the above code..
function checkType() {
var foo = function() {}; /* function will be hoisted to the top,
and will be assigned to the variable as
the name is the same for the two.. */
return foo;
// Code will never reach here as you are returning before this
foo = 10;
foo = 11;
};
console.log(typeof checkType());
Functions which are defined using function() syntax will be hoisted, in this case, the nested function will be hoisted insde the checkType() and hence, the checkType() returns the function instead of the integer.
Note: Because the function was defined using function(){} syntax, it
was hoisted to the parent function scope, else, if the function was
defined using var foo = function() {} then the hoisting would not
have worked in the same way, your function would've returned undefined instead.
More reference on Scoping & Hoisting
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/
First all the function declarations are hoisted in a scope. So first of all the code moves the variable foo to the top of the scope and initialize its value to function.
The second declaration of variable is not hoisted because the function declaration is already hoisted. So the code is same as
function checkType() {
var foo = function(){}
return foo;
foo = 10;
foo = 11;
};
When we run a code there are two phase of it first is creation phase in this phase the syntax parser will read the code and hoist the function and variables, and second phase is execution phase in which the values are assigned to hoisted variables,
A point to note here is function are stored in memory during creation phase as it is where as the variables are hoisted but values
are not initialized ( which will be assigned during execution phase )
Compiler will treat your code like this after hoisting
function checkType() {
var foo = function() {}; //hoisted function
return foo;
foo = 10;
foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())
If you define your function as variable than it will be hoisted only but will not be initialized with value, you can see the below example
function checkType() {
return foo;
foo = 10;
var foo = function foo() {};
var foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())

Different JavaScript function format

I've been wondering what is the difference between:
function getBasicRow() {}
getBasicRow : function() {}
I've seen the 2nd function used by vtiger CRM and hifive (http://www.htmlhifive.com/)
The second one assigns the function to a property on some object literal, so the scope of the function is determined by the property.
The first one creates a named function without assigning it to a variable. The function will be hoisted to the closest function scope.
An elobrative explanation that I found here and would like to share it.
The different ways in which a function can be defined in javascript are:
function A(){}; // function declaration
var B = function(){}; // function expression
var C = (function(){}); // function expression with grouping operators
var D = function foo(){}; // named function expression
var E = (function(){ // immediately-invoked function expression (IIFE) that returns a function
return function(){}
})();
var F = new Function(); // Function constructor
var G = new function(){}; // special case: object constructor
What exactly is hoisting?
The interesting thing about these is that they are “hoisted” to the top of their scope, which means this code:
A();
function A(){
console.log('foo');
};
Gets executed as this code:
function A(){
console.log('foo');
};
A();
Which practically means that, yes, you can call the functions before they’re written in your code. It won’t matter, because the entire function gets hoisted to the top of its containing scope.
Variable declaration hoisting
Variable declarations are hoisted to the top of their scope, somewhat similarly to function hoisting except the contents of the variable are not hoisted as well. This happens with all variables, and it means it’s now happening with our functions, now that we’re assigning them to variables.
This code:
var A = function(){};
var B = function(){};
var C = function(){};
Will be executed as this:
var A, B, C; // variable declarations are hoisted
A = function(){};
B = function(){};
C = function(){};
Therefore the order of setting and calling this type of function is important:
// this works
var B = function(){};
B();
// this doesn't work
B2(); // TypeError (B2 is undefined)
var B2 = function(){};
The second example gives us an error because only the variable B2’s declaration is hoisted, but not its definition, thus the “undefined” error.
Courtesy: DavidBCalhoun

Does the var becomes a function because of a javascript function stored in a var?

In below example about Scope, I dont understand that how could a variable is running as a function? in here var f is running as f(). However, is this a sound method to run f in JavaScript? Why? Is it because var f stored a function?
var myFunction = function() {
var foo = "hello";
var myFn = function() {
console.log( foo );
};
foo = "ddd";
return myFn;
};
var f = myFunction();
f(); // "ddd"
Thanks!
This line of code will run the function myFunction and assign its return value to f.
var f = myFunction();
myFunction returns a reference to the function myFn. As a result, f is now a reference to myFn and when you attempt to call f using f() it calls myFn because that is where the reference points.
jsFiddle Demo
There is a similar approach which returns an object with functions
var init = function(){
return {
hello: function(){ console.log("hello"); },
world: function(){ console.log("world"); }
};
};
Which could then be used like this:
var f = init();
f.hello();
f.world();
In scripting languages in general and functional programming. You can use functions as you would a variable. For example: in both paradigms typically(not aware of any languages that don't) functions can be passed as parameters, etc...
Functions are objects in javascript, so they can be assigned to variables and passed around like any other value. And eventually they can be executed.
What's happening here is that myFunction returns a function, which can then of course be executed.
Let me simplify your example:
// function that returns a function.
var foo = function() {
// declare a function, but don't run it right now.
var fn = function() {
return "bar";
};
// return the function object.
return fn;
}
var someFn = foo(); // function object is returned from foo()
someFn(); // "bar" is returned
// Which means you could also do this!
// the first () executes foo, second () executes the function returned by foo()
foo()() // "bar" is returned
In this example, foo() returns a function. This function is saved to the local variable someFn and then executed.
Functions that return functions are a little tricky to wrap you head around sometimes, but it's one of the most powerful features of javascript as it allows you do some very tricky things.

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