Original Question:
JSHint complains when my JavaScript calls a function that is defined further down the page than the call to it. However, my page is for a game, and no functions are called until the whole thing has downloaded. So why does the order functions appear in my code matter?
EDIT: I think I may have found the answer.
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
I am groaning inside. Looks like I need to spend ANOTHER day re-ordering six thousand lines of code. The learning curve with javascript is not steep at all, but it is very loooooong.
tl;dr If you're not calling anything until everything loads, you should be fine.
Edit: For an overview which also covers some ES6 declarations (let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
This weird behavior depends on
How you define the functions and
When you call them.
Here's some examples.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
This is because of something called hoisting!
There are two ways to define functions: Function declaration and function expression. The difference is annoying and minute, so let's just say this slightly wrong thing: If you're writing it like function name() {}, it's a declaration, and when you write it like var name = function() {} (or an anonymous function assigned to a return, things like that), it's a function expression.
First, let's look at how variables are handled:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Now, how function declarations are handled:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
The var statements "throws" the creation of foo to the very top, but doesn't assign the value to it yet. The function declaration comes next in line, and finally a value is assigned to foo.
And what about this?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Only the declaration of foo is moved to the top. The assignment comes only after the call to bar is made, where it was before all the hoisting occurred.
And finally, for conciseness:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Now, what about function expressions?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Just like regular variables, first foo is declared at the highest point of the scope, then it is assigned a value.
Let's see why the second example throws an error.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
As we've seen before, only the creating of foo is hoisted, the assignment comes where it appeared in the "original" (un-hoisted) code. When bar is called, it is before foo is assigned a value, so foo === undefined. Now in the function-body of bar, it's as if you're doing undefined(), which throws an error.
The main reason is probably that JSLint does only one pass on the file so it doesn't know you will define such a function.
If you used functions statement syntax
function foo(){ ... }
There is actually no difference at all where you declare the function (it always behaves as if the declaration is on the beginning).
On the other hand, if your function was set like a regular variable
var foo = function() { ... };
You have to guarantee you wont call it before the initialization (this can actually be a source of bugs).
Since reordering tons of code is complicated and can be a source of bugs in itself, I would suggest you search for a workaround. I'm pretty sure you can tell JSLint the name of global variables beforehand so it doesn't complain about undeclared stuff.
Put a comment on the beggining of the file
/*globals foo1 foo2 foo3*/
Or you can use a text box there for that. (I also think you can pass this in the arguments to the inner jslint function if you can meddle with it.)
There are way too many people pushing arbitrary rules about how JavaScript should be written. Most rules are utter rubbish.
Function hoisting is a feature in JavaScript because it is a good idea.
When you have an internal function which is often the utility of inner functions, adding it to the beginning of the outer function is an acceptable style of writing code, but it does have the drawback that you have to read through the details to get to what the outer function does.
You should stick to one principle throughout your codebase either put private functions first or last in your module or function. JSHint is good for enforcing consistency, but you should ABSOLUTELY adjust the .jshintrc to fit your needs, NOT adjust your source code to other peoples wacky coding concepts.
One coding style that you might see in the wild you should avoid because it gives you no advantages and only possible refactoring pain:
function bigProcess() {
var step1,step2;
step1();
step2();
step1 = function() {...};
step2 = function() {...};
}
This is exactly what function hoisting is there to avoid. Just learn the language and exploit its strengths.
Only function declaration are hoisted not function expression (assignment).
Related
Original Question:
JSHint complains when my JavaScript calls a function that is defined further down the page than the call to it. However, my page is for a game, and no functions are called until the whole thing has downloaded. So why does the order functions appear in my code matter?
EDIT: I think I may have found the answer.
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
I am groaning inside. Looks like I need to spend ANOTHER day re-ordering six thousand lines of code. The learning curve with javascript is not steep at all, but it is very loooooong.
tl;dr If you're not calling anything until everything loads, you should be fine.
Edit: For an overview which also covers some ES6 declarations (let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
This weird behavior depends on
How you define the functions and
When you call them.
Here's some examples.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
This is because of something called hoisting!
There are two ways to define functions: Function declaration and function expression. The difference is annoying and minute, so let's just say this slightly wrong thing: If you're writing it like function name() {}, it's a declaration, and when you write it like var name = function() {} (or an anonymous function assigned to a return, things like that), it's a function expression.
First, let's look at how variables are handled:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Now, how function declarations are handled:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
The var statements "throws" the creation of foo to the very top, but doesn't assign the value to it yet. The function declaration comes next in line, and finally a value is assigned to foo.
And what about this?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Only the declaration of foo is moved to the top. The assignment comes only after the call to bar is made, where it was before all the hoisting occurred.
And finally, for conciseness:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Now, what about function expressions?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Just like regular variables, first foo is declared at the highest point of the scope, then it is assigned a value.
Let's see why the second example throws an error.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
As we've seen before, only the creating of foo is hoisted, the assignment comes where it appeared in the "original" (un-hoisted) code. When bar is called, it is before foo is assigned a value, so foo === undefined. Now in the function-body of bar, it's as if you're doing undefined(), which throws an error.
The main reason is probably that JSLint does only one pass on the file so it doesn't know you will define such a function.
If you used functions statement syntax
function foo(){ ... }
There is actually no difference at all where you declare the function (it always behaves as if the declaration is on the beginning).
On the other hand, if your function was set like a regular variable
var foo = function() { ... };
You have to guarantee you wont call it before the initialization (this can actually be a source of bugs).
Since reordering tons of code is complicated and can be a source of bugs in itself, I would suggest you search for a workaround. I'm pretty sure you can tell JSLint the name of global variables beforehand so it doesn't complain about undeclared stuff.
Put a comment on the beggining of the file
/*globals foo1 foo2 foo3*/
Or you can use a text box there for that. (I also think you can pass this in the arguments to the inner jslint function if you can meddle with it.)
There are way too many people pushing arbitrary rules about how JavaScript should be written. Most rules are utter rubbish.
Function hoisting is a feature in JavaScript because it is a good idea.
When you have an internal function which is often the utility of inner functions, adding it to the beginning of the outer function is an acceptable style of writing code, but it does have the drawback that you have to read through the details to get to what the outer function does.
You should stick to one principle throughout your codebase either put private functions first or last in your module or function. JSHint is good for enforcing consistency, but you should ABSOLUTELY adjust the .jshintrc to fit your needs, NOT adjust your source code to other peoples wacky coding concepts.
One coding style that you might see in the wild you should avoid because it gives you no advantages and only possible refactoring pain:
function bigProcess() {
var step1,step2;
step1();
step2();
step1 = function() {...};
step2 = function() {...};
}
This is exactly what function hoisting is there to avoid. Just learn the language and exploit its strengths.
Only function declaration are hoisted not function expression (assignment).
I'm not really a javascript noob at all, although in my whole life I've never came across this, but am I right in assuming that javascript must assign functions before running anything or something?
In all my experience, I expected this to return 'undefined', but obviously it returns 'function'.
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
alert(typeof bar());
Is someone able to explain this for me?
This behaviour of JavaScript is called hoisting. There is a good explanation on the MDN (https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
In JavaScript, functions and variables are hoisted. Hoisting is JavaScript's behavior of moving declarations to the top of a scope (the global scope or the current function scope).
That means that you are able to use a function or a variable before it has been declared, or in other words: a function or variable can be declared after it has been used already.
Basically, if you declare a variable like this:
console.log(s); // s === undefined
var s = 'some string';
s declaration will be "hoisted" to the beginning of the scope (i.e. there will be no ReferenceError on the line with console.log). The variable's value will not be defined at that moment though.
The same goes with assigning an anonymous function to a variable, so:
console.log(f); // f === undefined
f(); // TypeError: f is not a function
var f = function () {}; // assigning an anonymous function as a value
f(); // ok, now it is a function ;)
The variable will be hoisted and thus visible in the entire scope, but it's value, even if it's a function, will still be undefined - hence the error if you try to execute it.
On the other hand if you declare a named function:
console.log(f); // f === function f()
f(); // we can already run it
function f() {}; // named function declaration
It's definition will also be hoisted so you can run it even in the first line of the scope you've declared it.
This is quite easily tested;
foo(1);
function foo(i) {
if (bar()) {
alert("foo called, bar true, i = " + i);
};
}
foo(2);
function bar() {
return true;
}
foo(3);
DEMO
This shows that Javascript loads all functions before executing anything. Therefor it does not matter what order functions are defined.
Well in JavaScript function is nothing but Object.
When you say typeof bar(),in the bar function you are returning foo which is another function.You just returning name of the function,So,it return the constructor of the foo function.So,your typeof get the value of foo constructor which is type of function.So,it alert function.It still refer the foo because of closure
Again in the bar defination,you returning foo,but its definition is still not encountered.In JavaScript when while parsing the instruction,declaration of variable and function is placed on top in current function scope.
So,
your statement
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
is equivalent to
function bar() {
function foo() {}
return foo;
foo = 10;
var foo = '11';
This is called JavaScript top hoist
}
I came across a interesting quiz
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
alert(typeof bar());
My interpretation is like this (Which is wrong according to console :) ):
var foo; // global variable
function bar(){
function foo(){}
var foo; // Here variable foo should override foo function
return foo; // (according to me foo should be variable with undefined value) What is going on here, How JavaScript resolve naming order ?
foo = 10;
foo = "11";
}
Here is a reference which I am reading this
In JavaScript, a name enters a scope in one of four basic ways:
1.Language-defined: All scopes are, by default, given the names this and arguments.
2. Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function.
3. Function declarations: These are of the form function foo() {}.
4. Variable declarations: These take the form var foo;
He later quoted :
The most important special case to keep in mind is name resolution order. Remember that there are four ways for names to enter a given scope. The order I listed them above is the order they are resolved in. In general, if a name has already been defined, it is never overridden by another property of the same name. This means that a function declaration takes priority over a variable declaration. This does not mean that an assignment to that name will not work, just that the declaration portion will be ignored.
Which is confusing for me, Can anyone simplify this with reference to above example ?
Main point I want to know :
How variables without var inside a function hoisted ?
Does variable overriding occurs during hoisting ?
Lets leave the function foo for the moment. Within a function, if a variable is declared anywhere inside that function, the declaration will be moved to the top of the function. So, it is actually evaluated like this
function bar() {
var foo;
return foo;
foo = 10;
foo = '11';
}
But when you have a function declared by the same name, it will take precedence and it will be evaluated similar to this
function bar() {
var foo = function() {};
return foo;
foo = 10;
foo = '11';
}
That is why you are getting function in the alert box.
Any variable without var inside a function becomes a global variable by default.
when you have a function declaration inside another function(like in your example), it gets hoisted first followed by the variable declarations.
examples to demonstrate variable overriding.
function bar() {
var foo = 10;
function foo() {}
return foo;
}
bar(); //--> returns 10;
function bar() {
var foo;
function foo() {}
return foo;
}
bar(); //--> returns the function object foo.
JSLint does not like this code saying "'b' was used before it was defined"
var a = function () {
b();
},
b = function () {
alert("Hello, world!");
};
a();
but perfectly happy with this
var a, b;
a = function () {
b();
};
b = function () {
alert("Hello, world!");
};
a();
But I am not defining anything in my second code snippet. I am merely declaring variable b.
So why is JSLint doing this? Is there a reason I should be declaring all my functions first?
PS I understand I could have just changed order of a and b, but in real project my functions are event handlers and sometimes they call each other, so it is probably not possible.
If your code is well-written and object-oriented, it is possible to declare your functions before they are used. But JSLint sets a lot of standards that really have little relevance to the functionality of your application, and I really doubt there are any performance implications declaring functions one way or the other.
So why is JSLint doing this? Is there a reason I should be declaring all my functions first?
Yes, otherwise there might be some unexpected errors. Your code works because of JavaScript's "Hoisting". This mechanism pulls up all declarations, implicit or explicit and can cause some unexpected results.
Consider this code:
var s = "hello"; // global variable
function foo() {
document.write(s); // writes "undefined" - not "hello"
var s = "test"; // initialize 's'
document.write(s); // writes "test"
};
foo();
It's being interpreted as follows:
var s = "hello"; // global variable
function foo() {
var s; // Hoisting of s, the globally defined s gets hidden
document.write(s); // writes "undefined" - now you see why
s = "test"; // assignment
document.write(s); // writes "test"
}
foo();
(example taken from the german Wikipedia page: http://de.wikipedia.org/wiki/Hoisting)
In C it is what we call forward declaration, looks like it could be the same in JSLint.
JSLint is aware of b and at that point b could be a function for all it cares (but if it isn't a function, it would throw an error of course)
I'm a little confused.
Everywhere i look, people say that i should use self invoking functions for scoping reasons, to avoid global namespace pollution.
But in this aspect, self invoking function seems to act identically to regular function, as in this example:
function xx(){
var x="variable";
//logs into console
console.log(x);
}
xx();
//logs undefined
console.log(x);
So, only real difference with regular function and self invoking is "self invoking" part, meaning i just don't have to run function manually after declaration?
A “self-invoking function” is a name for a common JavaScript idiom. It’s not actually a type of function; it’s the immediate execution of a function. You can call it an IIFE for “immediately invoked function expression” instead if that helps.
(function () { // Anonymous function expression
// IIFE!
})(); // Invocation happens here with the ()!
var f = (function () { // Still anonymous
// Almost immediately invoked function expression!
});
f(); // Invocation happens here!
var f = (function f() { // Not anonymous – now called “f”
// Almost immediately invoked function expression!
});
f(); // Invocation happens here!
function f() { // Not anonymous
// Almost immediately invoked function *declaration* – not an expression!
}
f(); // Invocation happens here!
Self-invoking functions are normal functions, but don't have a name. That makes them impossible to call except immediately after being declared, which effectively makes them a one-time-use function that is forever hidden from other code.
As you point out, the form
function foo() {
console.log("foo");
}
foo()
and
(function () {
console.log("foo");
})()
behave identically.
However, the first form with function foo() {... creates a named function that lives in that scope until the scope is destroyed. For the global scope, that will never happen, leaving foo a valid and callable identifier for any other code in your application.
That means that at any time, anybody else can do
foo()
and either initialize your module again or, potentially, obtain a handle to a new copy of the module.
At best, this can cause confusion and duplicate state. At worst, depending on how your IIFE is structured, they may be able to dig into hidden state and start manipulating it in ways you don't expect.
Writing a function that is both anonymous and immediately invoked prevents anyone from ever invoking it again, making it a clean and safe way to create and use a completely hidden scope. That's why you see it used so often to provide private state or construct a module.
They must have confused a IIFE with "self-invoking function".
Here's something Ben Alman wrote:
What’s wrong with “Self-executing anonymous function?”
You’ve already seen it mentioned a few times, but in case it wasn’t clear, I’m proposing the term “Immediately-Invoked Function Expression”, and “IIFE” if you like acronyms. The pronunciation “iffy” was suggested to me, and I like it, so let’s go with that.
What is an Immediately-Invoked Function Expression? It’s a function expression that gets invoked immediately. Just like the name would lead you to believe.
I’d like to see JavaScript community members adopt the term “Immediately-Invoked Function Expression” and “IIFE” in their articles and presentations, because I feel it makes understanding this concept a little easier, and because the term “self-executing anonymous function” isn’t really even accurate:
// This is a self-executing function. It's a function that executes (or
// invokes) itself, recursively:
function foo() { foo(); }
// This is a self-executing anonymous function. Because it has no
// identifier, it must use the the `arguments.callee` property (which
// specifies the currently executing function) to execute itself.
var foo = function() { arguments.callee(); };
// This *might* be a self-executing anonymous function, but only while the
// `foo` identifier actually references it. If you were to change `foo` to
// something else, you'd have a "used-to-self-execute" anonymous function.
var foo = function() { foo(); };
// Some people call this a "self-executing anonymous function" even though
// it's not self-executing, because it doesn't invoke itself. It is
// immediately invoked, however.
(function(){ /* code */ }());
// Adding an identifier to a function expression (thus creating a named
// function expression) can be extremely helpful when debugging. Once named,
// however, the function is no longer anonymous.
(function foo(){ /* code */ }());
// IIFEs can also be self-executing, although this is, perhaps, not the most
// useful pattern.
(function(){ arguments.callee(); }());
(function foo(){ foo(); }());
// One last thing to note: this will cause an error in BlackBerry 5, because
// inside a named function expression, that name is undefined. Awesome, huh?
(function foo(){ foo(); }());
Source : http://benalman.com/news/2010/11/immediately-invoked-function-expression/
// defined at `window`
function xx() {
var x = "variable";
//logs into console
console.log(x);
}
xx();
// not defined at `window`
(function yy() {
var y = "variable";
//logs into console
console.log("y:",y);
// `window["yy"]` : `undefined`
console.log("yy:", yy, "window['yy']:?", window["yy"]);
}());
console.log("xx", xx, window["xx"]);
try {
console.log("yy:", yy, window["yy"]);
} catch (e) {
console.log("yy:", e)
}
try {
console.log("x:", x);
} catch (e) {
console.log("x:", e)
}