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
var fn;
function foo() {
var a = 2;
function baz() {
console.log( a );
}
fn = baz; // assign baz to global variable
}
function bar() {
fn(); // look ma, I saw closure!
}
foo();
bar(); // 2
I have no idea with this code:
First, why the author have to wrap fn in a function that call fn(function bar), why don't call is simply outside the global scope like "fn();",I've tried it and result in the same
Second, is it a good way to assign a function to a variable?, I thought it could only copy the structure of the function and reconstruct in the variable(which means it have no reference or simply cannot remember the environment by foo)
Third, The author said that engine remain all the closure whenever there is one who using what concern to that environment, but here, I just see that there's a assignment, so is it right if fn is using baz that leads to the remain of environment of foo to fn?(which make fn can use the variable "a")
In Douglas Crockford's book he writes a recursive function as:
var walk_the_DOM = function walk(node, func){
func(node);
node = node.firstChild;
while(node){
walk(node,func);
node = node.nextSibling;
}
}
I've never seen a function defined as var foo = function bar(){...} - I've always seen the right side of the declaration be anonymou as: var foo = function (){...}
Is the only purpose of the name walk in the right side of the declaration to shorten the calling of walk_the_DOM? They seem to become separate names for an identical function. Perhaps I've misunderstood how this snippet works.
Is there a functional reason for naming the function both in the variable declaration and the function construct?
Is there a functional reason for naming the function both in the variable declaration and the function construct?
Yes. function bar() {} causes the function's name property to be set to bar, which can be useful for, e.g., debugging in stack traces.
Regarding some of the naming confusion you alluded to, this might help:
function bar() {}
^ This is a function declaration, as it does not exist as part of an assignment expression.
var foo = function() {};
^ This is an assignment expression where the right-hand operand is a function expression, and where the function expression defines an anonymous function.
var foo = function bar() {};
^ This is an assignment expression where the right-hand operand is a function expression, and where the function expression defines a named function.
It's probably worth noting that function declarations can be referenced locally by their function name, so the following statements are roughly equivalent:
function bar() {}
var bar = function() {};
I say roughly equivalent, because the second statement still results in an anonymous function, rather than a named function. There's also a subtle difference in how function declarations get hoisted. Consider the following, for example:
function test() {
hello();
var hello = function () { console.log('hello'); };
}
test();
// > TypeError: hello is not a function
Note that hello was technically defined where we tried to invoke it (the exception is simply that it's not a function (yet)). This is due to variable hoisting. As expected, though, we haven't yet assigned our function to the hello variable. This is easier to show than to explain, really. Basically, due to hoisting, the above test example is equivalent to:
function test() {
var hello; // declared, but not assigned yet
hello();
hello = function () { console.log('hello'); }; // now the assignment happens
}
Compare that to an actual function declaration:
function test() {
hello();
function hello() { console.log('hello'); };
}
test();
// > "hello"
Notice that even though the declaration is below the invocation command, it still works, because function declarations get hoisted as a whole to the top of their scope (in this case, test).
If that's confusing, here's a more condensed description of behavior that might help: declarations get hoisted, not assignments. As long as you understand the difference between function declarations and function expressions, that's all you need to know. :)
By writing var foo = function (){...} you are declaring a variable named foo that holds an anonymous function. By writing var foo = function bar(){...} you are declaring a variable named foo that holds a named function as bar. As #jmar777 pointed out in his answer, this is useful to follow stack traces when debugging and bug fixing.
Here is the code I came across:
var foo=1;
function bar(){
foo=10;
return;
function foo(){}
}
bar();
alert(foo);
And the result is 1!
Just don't know why.
As far as my understanding, the first line defined a global variable 'foo' to the window object and the value is 1, then within the bar function assign the foo with 10, since there's no 'var' before foo, so the global variable 'foo' will be assigned with the value 10. Then return, the rest of the function won't be executed.
But it alerts 1.
While remove the function foo definition within the bar function, it will alert 10.
Welcome to the mysterious world of javascript hoisting :) Read this article, you will be enlightened: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
As a short answer: to make things work in javascript like this:
hello();
function hello() {
alert('hello');
}
Javascript first moves all function declarations to the top of your code, so you can call any functions "before" it was defined. I believe the reason why foo won't change to 10 if there is the function declaration is because it behaves like var foo;. You are defining a function locally, thus when it runs foo = 10; you are just overwriting the locally defined function foo() with the value 10.
The reason it's returning 1 is because the foo=10 is inside of the function bar()
so the foo=10 is a local variable and you have to call its function for the foo variable to change
for example if you do this it will alert 10
var foo=1;
function bar(){
foo=10;
return;
alert(foo);
}
bar();
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
There are two possible methods for pulling out a function in Javascript:
var foo = function() { ... }
This is a bit contrived; another common pattern is:
var foo = {
baz: 43,
doSomething: function() {
// ...
}
}
versus
function foo() {
// ...
}
Is there an explicit reason to prefer one or the other?
It all comes down to preference to where you declare your functions; hoisting.
Function declarations and variable declarations are always moved ("hoisted") invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:
function foo() {
bar();
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
bar();
x = 1;
}
Notice that the assignment portion of the declarations were not hoisted. Only the name is hoisted. This is not the case with function declarations, where the entire function body will be hoisted as well.
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
In this case, only the function declaration has its body hoisted to the top. The name 'foo' is hoisted, but the body is left behind, to be assigned during execution.
You can give names to functions defined in function expressions, with syntax like a function declaration. This does not make it a function declaration, and the name is not brought into scope, nor is the body hoisted.
foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
bin(); // ReferenceError "bin is not defined"
var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted)
foo(); // valid
bar(); // valid
baz(); // valid
bin(); // ReferenceError "bin is not defined"
So, if your preference is to have functions hoist to the top use a function declaration otherwise use expression. I prefer the latter as I typically build object literals with methods as function expressions.
Named function expressions can be handy when errors are thrown. The console will tell you what the function is instead of stating anonymous aka stack trace.
You've hit on a couple different things here, but I'll try to hit your main question first.
In general....
function() { ... } is a function expression. Syntaxically this is on the same level as 2 or [4,5]. This represents a value. So doing var foo=function(){ ... } will work as planned, every time.
function foo() { ... } is a function declaration. This might seem to do the same thing as var foo=function(){...}, but there's a small caveat. As its a declaration, it works similar to the concept of variable hoisting in JS (basically, all variable declarations are done before any expressions are evaluated).
A good example is from here:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
Basically variable hoisting has brought the value up to the top, so this code is equivalent (in theory) to :
function test() {
var foo;//foo hoisted to top
var bar=function(){//this as well
alert("this will run!");
}
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
}
NB: I'd like to take this spot to say that JS interpreters have a hard time following theory, so trusting them on somewhat iffy behaviour is not recommended. Here you'll find a good example at the end of a section where theory and practice end up not working (there are also some more details on the topic of expressions vs declarations).
Fun fact: wrapping function foo() {...} in parentheses transforms it from a declaration to an expression, which can lead to some weird looking code like
(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined
Don't do this if you don't have a reason to, please.
Summary var foo=function(){ ... } is *sorta kinda * the same as function foo(){ ... } except that the former does what you think it does where you think it should whereas the latter does weird stuff unless you wrap it in parens, but that messes up the scope, and JS interpreters allow you to do things that are considered syntax errors in the spec so you're led to believe that wrong things are in fact right, etc....
please use function expressions( var f=function(){...} ). There's no real reason not to, especially considering you're somewhat forced to do it when you're using dot syntax.
On to the second thing you touched.....
I'm not really sure what to say, it's kinda sorta completely different from everything else about this.
var foo = {
baz: 43,
doSomething:function() {
...
}
}
this is known as object literal syntax. JSON, which is based off of this syntax, is a pretty neat way of formatting data, and this syntax in JS is often used to declare new objects, with singleton objects for example(avoiding all the mess with declaring a function and using new ). It can also be used in the same way XML is used, and is preferred by all the cool kids...
Anyways, basically object literal syntax works like this:
{ name1: val1, .... namek:valk }
This expression is an object with certain values initialised on it. so doing var obj={ name1: val1, .... namek:valk } means that :
obj.name1==val1;
obj['name1']==val1;// x['y'] is the same thing as x.y
...
obj.namek==valk;
So what does this have to do with our example? Basically your expression is often used to declare singleton objects. But it can also be used to declare an object prototype, so someone can later do var newObj=Object.create(foo) , and newObj will have foo as a prototype.
Look into prototypal inheritence in detail if you want to really get how useful it is. Douglas Crockford talks about it in detail in one of his many talks).
There are few advantages to naming functions
names for meta analysis. functionInstance.name will show you the name.
Far more importantly, the name will be printed in stack traces.
names also help write self documenting or literate code.
There is a single disadvantage to named functions expressions
IE has memory leaks for NFE
There are no disadvantages to function declarations apart from less stylistic control
Your question really comprises of two parts, as you don't necessarily have to make your functions anonymous if they are assigned to a variable or property.
Named vs anonymous?
#Raynos highlights the main points clearly. The best part about named functions is that they will show themselves in a stack trace. Even in situations where functions are being assigned to variables/properties, it's a good idea to give your functions a name just to aid with debugging, however I wouldn't say anonymous functions are evil at all. They do serve a fine purpose:
Are anonymous functions a bad practice in JavaScript?
Function declaration vs function expression?
For that part of the question I would refer you to this question as it probably covers the topic in far more depth than I can
var functionName = function() {} vs function functionName() {}
Suppose I have functions like:
function foo() {
}
function bar() {
}
I can write above as Object Literal notation:
var Baz = {
foo: function() {
},
bar: function() {
}
};
As far as I understand in the later case, an instance of Baz will be created when the script loads regardless if any Baz function is ever called. In the former case, function object is only created when that function is called. Am I correct about these assumptions?
If I am correct then the former would have higher performance (less memory) than the later in application where these functions are rarely called.
But the advantage of the later is that it gives greater modularity and lower global namespace pollution.
What is your take on this from your professional experience?
Is there a speed difference?
In the former case, function object is only created when that function is called.
No, the functions are created regardless.
Note that you can also do this:
function foo() {
}
function bar() {
}
var Baz = {
foo: foo,
bar: bar
};
Or this:
var Baz = (function() {
function foo() {
}
function bar() {
}
return {
foo: foo,
bar: bar
};
})();
The primary purpose of putting the functions on Baz as properties is to make them available as "methods" on Baz. This might be for convenience, for "namespacing", etc. In your first form (and my first form above), if that code is at global scope, foo and bar are added to the global scope, which can get pretty crowded pretty fast (esp. on browsers). In your second example, the only global symbol is Baz because the functions are anonymous. In my final example above, the only global symbol is Baz but the functions aren't anonymous, they have names that debuggers and stack traces can show you (which is a good thing; more here).
In terms of trying to optimize when functions get created, here's how it works: When execution enters a given context (the global context, or the context related to calling a function), these things are done:
A behind-the-scenes execution context object is created.
A behind-the-scenes variable object for that execution context is created.
In the case of a function context:
A property is added to the variable object for arguments (the array-like thing you can use to access arguments)
A property is added to the variable object for each of the function's named arguments, with the value of the argument
If the function has a name, its name is added as a property of the variable object and has the value of the function object.
Properties are created on the variable object for each variable declared with var in the execution context; their values are initially undefined (regardless of whether the var has an initializer on it).
Every function declaration in the context is processed. (Function expressions are not processed yet; more on the difference below.) A property on the variable object for each function name is created and receives the function object as its value.
Step-by-step code execution begins.
Like all expressions, function expressions are evaluated when they're encountered in the step-by-step flow.
var statements that have initializers (e.g., var a = 2;) are treated exactly like assignment statements (a = 2;); the var aspect of it was done much earlier. (var is frequently misunderstood. For instance, we had this question just yesterday.)
You'll note the difference above between function declarations and function expressions. You can tell which is which by looking to see whether you're using the result as a right hand value — that is, are you assigning the result to a variable, using it as the right-hand side of a property definition in an object literal, or passing it into a function. If you are, it's a function expression. If you're not, it's a function declaration.
Function declaration example:
function foo() {
}
Function expression example:
var foo = function() {
};
Another:
var Baz = {
foo: function() { }
};
(The foo line is a property declaration in an object literal that uses a function expression for the value.)
Named function expression example:
var f = function foo() { // <== Don't do this (more below)
};
Named function expressions should be valid, but they're poorly-supported by implementations in the wild (particularly IE) and so for now they must be avoided. More here.