Jslint will call out errors if functions are defined out of order.
Obviously jslint is strict, but I wonder if there are any benefits to putting functions in order.
By that I mean defining them before they are called.
Function definitions (and var statements) are hoisted to the top of their closure. In other words, code is executing in an order that is not the same as what you wrote.
Now, there is nothing more "wrong" about it than leaving off the ; at the end of lines, but jsLint is designed to test the human-readability of the code. Jumping around isn't human-readable, so it's considered invalid.
If you define function before calling it, the code can be handled by one pass compiler, otherwise, you need a multi-pass compiler (which is slower in general).
Maybe there are some one pass JavaScript compilers out there (however, I don't know any).
I always think JSLint shows that error because it wants to make sure your code can run in a one pass compiler successfully
Depends.
This will succeed:
var x = y();
function y() { return 9; }
But this will fail:
var x = y();
var y = function() { return 9; };
When the first script is interpreted it will see function y and will make that function available throughout its scope (being the global scope in that example).
Whereas with the second example a function is assigned to y. And just like any other variable the order matters.
Related
In an online course, Kyle Simpson says the following code demonstrates the necessity of hoisting in javascript, because without hoisting "one of the functions would always be declared too late."
a(1) // 39
function a(foo){
if (foo > 20) return foo
return b(foo+2)
}
function b(foo){
return c(foo) + 1
}
function c(foo){
return a(foo*2)
}
But this works just fine.
var a = function(foo){
if (foo > 20) return foo
return b(foo+2)
}
var b = function(foo){
return c(foo) + 1
}
var c = function(foo){
return a(foo*2)
}
a(1) // 39
So what's the story? Convenience and placement of invocation aside, are there any situations that require hoisting?
The claim I've made about a non-hoisted JS being unable to support mutual recursion is just conjecture for illustration purposes. It's designed to help understand the need for the language to know about variables available in the scope(s). It's not a prescription for exact language behavior.
A language feature like hoisting -- actually hoisting doesn't exist, it's just a metaphor for variables being declared in scope environments ahead of time during compilation, before execution -- is such a fundamental characteristic that it can't easily be reasoned about when separated from the rest of the language's characteristics.
Morever, it is impossible to fully test this hypothesis in just JS. The snippet in the OP only deals with part of the equation, which is that it uses function expressions instead of function declarations to avoid function hoisting.
The language I was using to compare to for illustration is C, which for example requires function signatures to be declared in .h header files so that the compiler knows what a function looks like even if it hasn't "seen" it yet. Without it, the compiler chokes. That's a sort of manual hoisting in a sense. C does it for type checking, but one can imagine this sort of requirement existing for other reasons than that.
Another way of thinking about this is whether JS is a compiled language where everything has been discovered before it executes, or whether it is interpreted top-down in a single pass.
If JS were top-down interpreted, and it got to the definition of an a() function that referenced a b() inside it that it hadn't seen yet, that could be a problem. If that call expression was handled non-lazy, the engine couldn't figure out at that moment what the b() call would be about, because b() hadn't been processed yet. Some languages are lazy and some are non-lazy.
As is, JS is compiled first before execution, so the engine has discovered all the functions (aka "hoisting") before running any of them. JS also treats expressions as lazy, so together that explains why mutual recursion works fine.
But if JS had no hoisting and/or was not lazy, one can imagine the JS engine would be unable to handle mutual recursion because the circular reference between a() and b() would in fact mean that one of the two was always declared "too late".
That's really all I meant in the book.
Convenience and placement of invocation aside, there are not any situations that require hoisting.
Just make sure to declare all the functions before using them.
Note: In some browser, function a(){} creates a function with name a while var a = function(){} does not (considered anonymous function). The function name is used when debugging. You could also do var b = function a(){}.
The second block of code works fine because you are invoking a(1) after all the functions are initialized. Try the following block:
var a = function(foo){
if (foo > 20) return foo
return b(foo+2)
}
var b = function(foo){
return c(foo) + 1
}
a(1);
var c = function(foo){
return a(foo*2)
}
This will give an error Uncaught TypeError: c is not a function because function assigned to c is not hoisted. This is the reason why you need hoisting.
Because if you declare functions as in your first block of code, all the functions will be hoisted and you can invoke a anywhere in the code. This is not true in the other cases.
I have a function that looks like this:
function SomeFunction() {
var SomeVar;
if (SomeCondition) {
SomeVar = 4;
}
}
This is equivalent to:
function SomeFunction() {
if (SomeCondition) {
var SomeVar = 4;
}
}
Does using the var statement only if the condition is true make a difference or not, is there any best practice or performance implications concerning this?
Thanks.
Edit: yes, I am aware that there's no block scope, just function scope.
They function exactly the same, but there are two schools of thought about where to put it:
One group says you should put it at the top of the function, because that avoids the false impression you are relying on (nonexistent) block-scoping.
The other group says you should put it in the appropriate block, because that signals you intend to treat the variable as if it were block-scoped and not use it anywhere else.
As far as I know, I am the sole member of the second group.
Where the var statement is put has no effect on your code. This is purely a matter of style.
Some people feel that it's much clearer to put the var at the start of the function block. The lifetime of a variable in Javascript is tied to the function in which it's declared and not the scope. Many other curly brace languages do the opposite and this is a source of confusion for many new users. Hence people believe declaring at the start of the function leads to clearer code.
In JavaScript, there is no block scope for variables like in C/C++. Therefore, even if you declare your variable in the if () {} block, the variable is actually created immediately at the beginning of the function. This effect of "pulling declarations up" is usually called "hoisting".
Although both codes are correct, the first one is probably semantically better, as it emphasizes the fact that the variable exists regardless of whether SomeCondition is true.
Those are both actually equivalent. Read up on "hoisting" and "function and block scope".
As far as speed goes, you're better off using the second case - combining the declaration and assignment in the same statement. See: http://jsperf.com/stackoverflow-frenchie
Put it at the beginning of the function. It is always moved there anyway during the runtime, but it clears the confusion / untrue assumption if you put it where it is really executed.
So in you case, the first snippet.
(also, purely style, write identifier of everything except classes camelCase, not PascalCase)
I have a Sublimelinter installed in Sublime Text 2 and it's great. However it doesn't like the following code:
if(condition){
var result = 1;
}else{
var result = 2;
}
process(result);
It says for var result = 2; that result is already defined and for process(result); that it's used out of scope. Is it just mistaking the {} of the if statement for a more closed scope or should I really be doing it like this:
var result;
if(condition){
result = 1;
}else{
result = 2;
}
process(result);
No it is not "wrong"; it will get hoisted to the top of the nearest function definition, as per the ECMAScript specification.
Yes, your program "Sublimelinter" is incorrect to claim the variable is out of scope.
It is not wrong. If you get that error, you defined result earlier in your code.
You can also simplify your condition to this so you don't have to use result:
process( condition ? 1 : 2 );
Javascript doesn't have 'block-scoping' like many other languages. If it did, the variable result would not exist when you tried to call process(result) because it would not be possible to reference it outside of the {} block where it was defined.
However, javascript only has function scoping, where variables in one function cannot be accessed by another function. Where variables are declared in the function has no significance whatsoever, because it will still be accessible from anywhere inside that function (no block scope). Hence, both code snippets you posted are equivalence to whatever interpreter is running the code.
The second is preferable because it is clearer as it shows where the variable will be used (throughout the function). It also prevents the variable from being declared twice inside the scope of the function, which may not necessarily cause anything bad to happen, but it will definitely not cause anything beneficial. You should almost always declare a variable once at a higher level instead of twice at different lower levels, even though it doesn't really matter since the scope of the variable will be the entire function no matter where it is declared.
JavaScript does not have block scope. Variables are scoped to the function they are defined in, meaning that when you declare a variable inside of an if block, it is "hoisted" to the top of the function.
Since the variable is technically defined at the top of the function anyway, it is considered a best practice to move variable declarations to the top of the function so that the intent of the code is clear.
I'd say your code isn't "wrong" but it is misleading to people reading the code who aren't familiar with how scope works in JavaScript. I would definitely opt for the second version, because it actually reflects how the code is executed.
Here's a good article explaining variable hoisting.
Declare your var pointer once with-in the function you have your if statement at. Like ninjagecko mentioned all vars get sent to the top of their containing functions.
However; do be careful because if you declare the same var twice like you have it , it will reset the var.
I recommend doing this:
var result = MORE_LIKELY_OUTCOME;
if (LESS_LIKELY_CONDITION) {
result = LESS_LIKELY_OUTCOME;
}
process(result);
This way, you are setting result initially to what you are expecting it to be most of the times.
Then, the if statement will change result if the condition occurs.
It turns out that SublimeLinter is using JSHint which has the option to surpress this warning and explains why it exists.
funcscope This option suppresses warnings about declaring variables
inside of control structures while accessing them later from the
outside. Even though JavaScript has only two real scopes—global and
function—such practice leads to confusion among people new to the
language and hard-to-debug bugs. This is way, by default, JSHint warns
about variables that are used outside of their intended scope.
Many programming languages require a special user-written function that marks the begin
of the execution. For example, in C this function must always have the name main(). In
JavaScript, however, such a function is not required.
What are the logical reason for the absence of such a dedicated top level function in JavaScript? I know this is some kind of theoretical question, but I cannot find an answer online.
Because the entire code block is effectively one big main. In JavaScript, global code can have all of the constructs function code can have, and has stepwise execution, just like functions do. In fact, when the JS engine processes the code block as a whole, it does very nearly the same things that it does when processing a function call. See the specification's sections 10.4.1 ("Entering Global Code") and 10.4.3 ("Entering Function Code") and note how similar they are.
C doesn't allow stepwise code at the global level (you can have all sorts of initializers, and they can get kind of stepwise, but that's a different topic). And so C needs an explicit entry point (main). In JavaScript, the entry point is the beginning of the code.
Regarding your question below about whether global code is sequential. The answer is yes, it's exactly like code in a function that way. So:
var x, y, z;
x = 1;
y = 2;
z = x + y;
alert("z is " + z);
...will alert "z is 3". The code runs sequentially, top to bottom.
There are a couple of things that happen before the stepwise code is executed, though, which is useful to know. The most significant is that any declarations in the source text of the scope being entered are processed before the stepwise code begins. JavaScript has two main types of declarations: Variable declarations, and function declarations:
The name of any variable declared with var is added to the scope (with the value undefined) before any stepwise code is executed. (More: Poor, misunderstood var)
Function declarations are processed and the function names added to the scope before any stepwise code is executed. (JavaScript also has something else, called a function expression, which is stepwise code. More on that below.)
So for instance, in this source text:
var x;
x = 1;
foo();
function foo() {
}
the declarations are
var x;
function foo() {
}
and the stepwise code is
x = 1;
foo();
The declarations are processed first. This is why the call to foo works. (These same rules apply to the source text within functions.) This processing of declarations before anything else is sometimes called "hoisting," because the declarations are in a sense lifted from their location in the source text and moved to the very beginning. I prefer to think of it as two passes through the source: The first pass does declarations, the second executes stepwise code.
(Side note: Declaring a variable more than once in the same scope is perfectly legal [though pointless]. Declaring two functions with the same name is also legal; the latter declaration overrides the earlier one.)
(Side note 2: ES2015 [ES6] introduced let and const variable declarations, which behave somewhat differently from var. You can't declare a variable twice with them, they have block scope, and you can't use the variable prior to the statement where it's declared. So they're mostly not hoisted [there is something slightly like hoisting in that they prevent access to a shadowed variable in a containing scope even before the let x or whatever line].)
More detail, and possibly getting a bit technical:
var
If var happens before the stepwise code is run, you may be wondering about this:
var x = 1;
Does that happen before stepwise code, or as part of it? The answer is that in reality, that's just shorthand for two very different things:
var x;
x = 1;
The var x; part happens before the stepwise code, the x = 1; part is stepwise code and is executed when we reach it in the sequence. So:
alert(x); // "undefined" -- there **is** a variable `x`; it has the value `undefined`
var x = 1;
alert(x); // "1" -- now `x` has the value `1`
Function declarations
JavaScript has two different, but very similar-looking, things: Function declarations, and function expressions. You can tell which is which by whether you're using the resulting function as part of the expression in which it's defined.
Here's a function declaration:
function foo() {
}
These are all function expressions (we use the resulting function value as part of the expression; in computer science terminology, the function is used as a right-hand value):
// 1: Assigning the result to something
var x = function() {
};
// 2: Passing the result into a function
bar(function() {
});
// 3: Calling the function immediately
(function(){
})();
// 4: Also calling the function immediately (parens at end are different)
(function(){
}());
// 5: Also calling the function immediately
!function(){
}();
// 6: Syntax error, the parser needs *something* (parens, an operator like ! or
// + or -, whatever) to know that the `function` keyword is starting an *expression*,
// because otherwise it starts a *declaration* and the parens at the end don't make
// any sense (and function declarations are required to have names).
function(){
}();
The rule is that function declarations are processed before the stepwise code begins. Function expressions, like all other expressions, are processed where they're encountered.
One final side note: This is a named function expression:
var f = function foo() {
};
We use it as a right-hand value, so we know it's an expression; but it has a name like function declarations do. This is perfectly valid and legal JavaScript, and what it's meant to do is create a function with a proper name (foo) as part of the stepwise code. The name of the function is not added to the scope (as it would be if it were a function declaration).
However, you won't see named function expressions in very many places, because JScript (Microsoft's JavaScript engine) gets them horribly and utterly wrong, creating two separate functions at two different times.
JavaScript is event-driven, the program written in JavaScript doesn't have a start and an end. You can compare it to any desktop UI toolkit, where you handle button clicks and key presses, but there is no obvious main once the program is initialized.
For instance there is a window.onload event that is triggered when the page is loaded - and which you can handle.
in a scripting language, the code is executed from the first line in the file to the end as if it was being typed into an interpreter. (this doesn't preclude parsing and compiling the code as long as those process don't effect the denotational semantics described.)
Javascript,python and PHP there are scripting language. These programming languages are not using main() function.
You already know the answer
In JavaScript, however, such a function is not required!
JavaScript is scripting language while C needs to be compiled.
In essence, I am trying to declare a variable in the condition-part of a while loop in javascript:
while (var b=a.pop()) {
do_sth(b)
}
Yet, my browser (firefox) doesn't accept that. Instead I have to go like so:
var b
while (b=a.pop()) {
do_sth(b)
}
which works. Is this behaviour expected?
Yes, it is.
If you want to, you can use a for loop, like this:
for (var b; b = a.pop(); ) { //Note the final semicolon
do_sth(b);
}
The question is a little dated, but I think the answers all miss an important distinction. That is, a while loop expects an expression that evaluates to a conditional, i.e., a boolean or value that can be converted to a boolean. See Mozilla docs for details.
A pure assignment (without instantiation) is coerced to a boolean via its default return value (the value of the right-hand-side).
A var (or let or const) is a statement that allows an optional assignment but has a return value of undefined.
You can easily test this in your console:
var foo = 42; // undefined
bar = 42 // 42
The return values alone don't answer the question, since undefined is falsey, but does show that even if JS let you put a var in a conditional it would simply always evaluate to false.
Others have mentioned for statements and that they allow declaration and instantiation of variables. This is true, but the documentation explains that for expects a statement or assigment.
Opinions may vary, but for me all this adds up to an understandable consistency not a quirk in behavior with regard to loops. A while loop is better thought of as a looping version of an if statement than akin to a for loop. If there is quirkiness in all of this, it's the for statement's wholesale divergence from the language's normal syntax.
JavaScript does not have block scope. It has function scope. So to make sure that humans and JavaScript both read the code the same way, you should manually hoist your var declarations right up to the top of functions.
Here's what JSLint says about your code:
Problem at line 1 character 8: Expected an identifier and instead saw 'var'.
Use JSLint, at least while you're learning JavaScript. You'll learn a lot very quickly. It will hurt your feelings.
JavaScript doesn't have block scope. So all var declarations are at function scope. So declaring a variable in a while expression doesn't make sense in JavaScript.
Additionally, you should end your statements with a semicolon. It's not strictly necessary, but it's highly recommended.