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);
Related
I know that function expressions resolve to a value (not to be confused with what they return [as others cleared up for me in another SO question)—all functions return undefined by default), hence the word "expression," whereas function declarations don't. But I'm not sure what exactly is causing this discrepancy. My initial guess was that it is the variable assignment (given what's to the right of the assignment operator is always an expression [I think]), but function expressions don't require variable assignment. To my knowledge the only other difference (besides resolving to a value) between them and function declarations is that you can omit the function name in a function expression. I'd appreciate any insight.
Refer :https://javascript.info/function-expressions-arrows#function-expression-vs-function-declaration
A Function Expression is created when the execution reaches it and is usable from then on.
Once the execution flow passes to the right side of the assignment let sum = function… – here we go, the function is created and can be used (assigned, called etc) from now on.
Function Declarations are different.
A Function Declaration is usable in the whole script/code block.
In other words, when JavaScript prepares to run the script or a code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an “initialization stage”.
And after all of the Function Declarations are processed, the execution goes on.
As a result, a function declared as a Function Declaration can be called earlier than it is defined.
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}
The Function Declaration sayHi is created when JavaScript is preparing to start the script and is visible everywhere in it.
…If it was a Function Expression, then it wouldn’t work:
sayHi("John"); // error!
let sayHi = function(name) { // (*) no magic any more
alert( `Hello, ${name}` );
};
Function Expressions are created when the execution reaches them. That would happen only in the line (*). Too late.
When a Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.
Sometimes that’s handy to declare a local function only needed in that block alone. But that feature may also cause problems.
For instance, let’s imagine that we need to declare a function welcome() depending on the age variable that we get during runtime. And then we plan to use it some time later.
let age = prompt("What is your age?", 18);
// conditionally declare a function
if (age < 18) {
function welcome() {
alert("Hello!");
}
} else {
function welcome() {
alert("Greetings!");
}
}
// ...use it later
welcome(); // Error: welcome is not defined
That’s because a Function Declaration is only visible inside the code block in which it resides.
Here’s another example:
let age = 16; // take 16 as an example
if (age < 18) {
welcome(); // \ (runs)
// |
function welcome() { // |
alert("Hello!"); // | Function Declaration is available
} // | everywhere in the block where it's declared
// |
welcome(); // / (runs)
} else {
function welcome() { // for age = 16, this "welcome" is never created
alert("Greetings!");
}
}
// Here we're out of curly braces,
// so we can not see Function Declarations made inside of them.
welcome(); // Error: welcome is not defined
What can we do to make welcome visible outside of if?
The correct approach would be to use a Function Expression and assign welcome to the variable that is declared outside of if and has the proper visibility.
Now it works as intended:
let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("Hello!");
};
} else {
welcome = function() {
alert("Greetings!");
};
}
welcome(); // ok now
Or we could simplify it even further using a question mark operator ?:
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ?
function() { alert("Hello!"); } :
function() { alert("Greetings!"); };
welcome(); // ok now
I understanding how hoisting in javascript occurs, functions are hoisted before variables, and only the declarations are hoisted. But When I came across hoisting inside if/else conditionals, like this one:
foo(); // "b is the output"
var a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
Now the conditional is true, so according to the if block, a should have been the output, but due to some kind of hoisting I assume b is the output.
So how is b the output?
In JavaScript, variables, function expressions and function declarations are hoisted to the top of the scope.
Function declarations defines a named function variable without requiring variable assignment.
And important to know is that the entire body of the function declaration gets hoisted up the scope.
E.g.
function outerFunction() {
console.log(typeof functionDeclaration); // outputs "function"
function functionDeclaration() {
// ... function body
}
}
This is because, because of hoisting the code runs like so:
function outerFunction() {
function functionDeclaration() {
// ... function body
}
console.log(typeof functionDeclaration); // outputs "function"
}
In your case, the last function declaration for foo is hoisted to the top of the scope overriding all the other function declarations. Therefore, it logs "b".
Variables and function expressions, however, get hoisted without their assigned values.
E.g.
function outerFunction() {
console.log(functionExpression); // outputs "undefined"
var functionExpression = function () {
// ... function body
}
}
Runs more like so,
function outerFunction() {
var functionExpression = undefined;
console.log(functionExpression); // outputs "undefined"
functionExpression = function () {
// ... function body
}
}
(Ignoring the slightly dodgy behaviour that certain old browsers may have had:)
In Javascript, function statements are scoped within the containing function (or globally if there is no containing function), they're not scoped within an if or else or loop block. So you can't declare a function conditionally in that manner (it can be done another way; see below). And if you declare more than one function with the same name in the same scope the later one will overwrite the first one.
So what happens with your code is:
Both function statements are hoisted, but
They both have the same name so the first is overwritten by the second.
The variable, a is created but not yet assigned a value.
The foo() statement is executed, logging "b"
a is assigned the value true.
The if is executed. The condition is true, but neither the if nor else branches actually do anything because they don't contain statements other than the function declarations that were hoisted earlier.
If you want to create functions conditionally you have to declare a variable and then assign a function expression to it. And then you can not call the function until after that assignment:
var foo;
var a = true;
if(a)
foo = function() { console.log("a"); };
else
foo = function() { console.log("b"); };
foo();
The is not the correct behavior anymore in modern JS browsers! The modern browsers will compile and hoist the mentioned code like this:
// hoisting (treat foo declarations as a normal variable declaration inside if statement)
var a;
var foo;
// now the assignment
foo(); // TypeError (foo = undefined)
a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
This is a unspecified behavior, different browser behaves diffrently.
MDN explain
In chrome & firefox, it will output foo is not a function.
And in safari, it will output b.
another doc of MDN
var abc = function() {
console.log(1);
}
function abc() {
console.log(2);
}
abc();
I am expecting that it will console 2, but no it will console 1 because of
function and variable hoisting.Anybody who want to make it more clear.
In JavaScript, a name enters a scope in one of four basic ways and the order of hoisting follows following order...
Language-defined: All scopes are, by default, given the names this and arguments
Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function
Function declarations: These are of the form function foo() {}
Variable declarations: These take the form var foo;
Reference: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
In your case the 1st function is type 4 and the second function is type 3. Therefore the second function is hoisted first assigning the function reference to abc. And then the first function is hoisted reassigning the reference to abc. Your code is compiled in following order,
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
}
abc();
Note that only declarations are hoisted. Assignments are not hoisted.
var bar = 'test';
var foo = function(){/*foo 1*/};
var foo;
function foo(){/*foo 2*/}
alert(foo);
will be complied in this order,
function foo(){/*foo 2*/} //function declaration
var bar; //variable declaration
var foo; //variable declaration
bar = 'test';
foo = function(){/*foo 1*/};
alert(foo);
var hoisting
the Key to understanding how scope in JavaScript works is understanding the concept of hoisting.
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declared. This
behavior is called "hoisting", as it appears that the variable
declaration is moved to the top of the function or global code.
console.log("function hoisting:::: ",abc()); /* log = 2 we are calling the function(hoisting)*/
var abc = function() {
console.log(1);
};
console.log("var:::: ",abc()); /* log = 1*/
function abc() {
console.log(2);
}
abc(); /* log = 1*/
console.log("function:::: ",abc()); /* log = 1*/
So in your case you are not calling the function, to call the function log it on the top.
this is how the javascript engine interprets it
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
};
abc();
REF: JavaScript Scoping and Hoisting
If you're simply asking why the function abc isn't the one being executed despite it being declared most recently, it's because, In Javascript, functions are hoisted to the top of the current scope.
That means your code is morphed into something like the following:
function abc() { console.log(2); }
var abc = function() { console.log(1); }
abc();
That means, when it comes time to call abc, the "active" one is the one that logs 1.
One of the best articles I ever found on this behaviour was the one over at adequately good.
I was playing around with javascript objects to understand "this" and function context better. I stumbled across this problem. I get the error "obj2 is not defined" unless I run window.obj2() after assigning it, but I don't know why. Shouldn't it be enough to assign the function to window.obj2 without also executing it immediately afterwards? I know that you're not supposed to pollute the window object, this is just a test.
Thanks!
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
window.obj2(); // problem when this line is commented out
(function () {
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}());
EXPLANATION
OP asks why does he have to execute the function after defining it in order for it to become defined later in the code... See what happens when you comment out the problem line.
Solution to the mystery:
You forgot a semicolon:
window.obj2 = function(){
console.log('obj2 in window.object',this);
}; // <--
Without it, the code will be interpreted as
// I'm naming the functions to refer to them later
window.obj2 = function a(){
...
}(function b() { ... }());
I.e. the parenthesis around b are interpreted as call operation of a (just like you did with b itself: (function b() {...}()).
The engine first executes b in order to pass the return value as argument to a, and only after that the return value is assigned to window.obj2.
So, at the moment b is called, window.obj2 does indeed not exist yet.
So, the reason why adding window.obj2() makes it work is not because you are accessing window.obj2, but because it makes the code un-ambigious. The following parenthesis cannot be interpreted as call operation anymore. You could use any statement there, e.g.
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
"foo";
(function () {
obj2();
}());
If you defined function window.obj2 inside the anonymous function which does call itself then it works fine, have a look code.
<script>
//window.obj2(); // problem
(function (window) {
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}(window));
</script>
<body>
</body>
What is the different between two declarations of a module in JavaScript?
One has parentheses around the function and other one doesn't?
One article says that
Notice the () around the anonymous function. This is required by the
language, since statements that begin with the token function are
always considered to be function declarations. Including () creates a
function expression instead.
Both seem to do the same thing when checked.
var person = (function () {
// Private
var name = "Robert";
return {
getName: function() {
return name;
},
setName: function(newName) {
name = newName;
}
};
}());
var person = function () {
// Private
var name = "Robert";
return {
getName: function() {
return name;
},
setName: function(newName) {
name = newName;
}
};
}();
Functions are of two types in JavaScript - declarations and expressions.
This is the difference between the two:
Function declarations are hoisted. This means you can call the function before it appears in the program as declarations in JavaScript are hoisted.
Function expressions can be invoked immediately. A function declaration cannot. This is because expressions express (or return a value). Function expressions express a function.
An example of a function declaration:
foo("bar");
function foo(bar) {
alert("foo" + bar);
}
The above program will work because foo is a function declaration.
foo("bar"); // throws an error, foo is undefined - not a function
var foo = function (bar) {
alert("foo" + bar);
};
The above program will not work as foo is declared as undefined, hoisted and then later assigned the value of a function expression. Hence it's undefined when it's called.
An example of a function expression:
(function (bar) {
alert("foo" + bar);
}("bar"));
The above function will be immediately invoked as it's a function expression.
function (bar) {
alert("foo" + bar);
}("bar"); // throws an error, can't call undefined
The above function will not be immediately invoked as it's a function declaration. Remember, declarations do not express (or return a value). So it's like trying to invoke undefined as a function.
How does a function become an expression?
If a function is used in the context where an expression is expected then it's treated as an expression. Otherwise it's treated as a declaration.
Expressions are expected when:
You're assigning a value to a variable (i.e. identifier = expression).
Inside parentheses (i.e. ( expression )).
As an operand of an operator (i.e. operator expression).
Hence the following are all function expressions:
var foo = function () {};
(function () {});
~function () {};
Everything else is a function declaration. In short if your function is not preceded by anything, it's a declaration.
See this code: https://github.com/aaditmshah/codemirror-repl/blob/master/scripts/index.js#L94
The following function isExpression is used to test whether some arbitrary JavaScript code is an expression or not:
function isExpression(code) {
if (/^\s*function\s/.test(code)) return false;
try {
Function("return " + code);
return true;
} catch (error) {
return false;
}
}
Hope this clears any doubts in your mind.
In short:
A function expression expresses or returns a value (in this case a function). Hence it can be immediately invoked, but it can't be called before it appears in the program.
A function declaration is hoisted. Hence it can be called before it appears in the program. However since it doesn't express any value it can't be immediately invoked.
In the current context there's no difference for the interpreter. Usually preferable way of writing module is by wrapping the function with parentheses:
var person = (function () {
// Private
var name = "Robert";
return {
getName : function () {
return name;
}
};
}());
That's because the syntax is cleaner and it's obviously that you want to invoke the function immediately after it is declared. One more reason is because:
(function () {
//some stuff
}());
will work but
function () {
//some stuff
}();
this wont.
By wrapping the function each time you use common codding style which is usually a good thing :-).
The difference is that when writing:
var foo = (function () {
...
}());
the use of the (superfluous but useful) grouping () is a common coding style to make it clear from very like first line that the right hand side is most likely an immediately invoked function expression (IIFE). However, in the second:
var foo = function () {
...
}();
it doesn't become apparent until you read the last line, which might be quite a few lines down. Until you reach the last line, you probably thought you were reading a plain assignment:
var foo = function () {
...
};
Note that the parenthesis can be used in a plain assignment too:
var foo = (function () {
...
});
but in that case they really are superfluous (and probably misleading due to the convention of using them for IIFEs).
See An Important Pair of Parens.