This question already has answers here:
Automatic semicolon insertion & return statements [duplicate]
(3 answers)
Closed 9 years ago.
I have seen this trick question online without any answer or description. Not sure what's going on here:
function identity() {
var name = 'Jack';
alert(name);
return
name
};
var who = identity();
alert(who)
This snipped outputs, jack & then undefined, why?
Change this
return
name
to this:
return name;
The return statement is one of the few places where javascript does not like whitespace. EDIT. What's happening in the original is the browser inserts a semicolon after the return statement, like this
return;
name // this gets ignored
So the return value is undefined.TehShrike links to a very good document explaining the exact rules ECMAAScript environments must follow when ignoring whitespace/line breaks and when semicolons must be inserted.
The ECMAScript standard says this (among other things)
Certain ECMAScript statements (empty statement, variable statement,
expression statement, do-while statement, continue statement, break
statement, return statement, and throw statement) must be terminated
with semicolons. Such semicolons may always appear explicitly in the
source text. For convenience, however, such semicolons may be omitted
from the source text in certain situations. These situations are
described by saying that semicolons are automatically inserted into
the source code token stream in those situations.
identity is a function. who then declares a new instance of that, which we can tell from the func that it will create a local variable name and assign jack to it, then alert.
The function then looks like it return nothing (although name is on the next line, so I'd imagine you want to return that, change to return name;).
Related
This question already has answers here:
TypeError: console.log(...) is not a function [duplicate]
(6 answers)
Closed 5 years ago.
It might interest somebody and save few hours, a nasty bundling problem, eval is from one file and function is from second file.
eval('console.log(0)')
(function(x){console.log(x)})(1)
will result with: Uncaught TypeError: eval(...) is not a function
and this is the fix
eval('console.log(0)');
(function(x){console.log(x)})(1)
missing semicolon, I've read few times that semicolon in JS optional most of the time.
any comments why eval is not a function in this context?
The JS runtime is not perfect at guessing where semi-colons should go.
When it sees this:
eval('console.log(0)')
(function(x){console.log(x)})(1)
It incorrectly assumes that the result of the immediately invoked function expression is part of the eval line (a potential parameter to be passed to the potential function that the eval evaluates to).
Here's an example of when that would work:
eval("(function(message){ alert(message); })")
("Hi there!");
But, in your case, eval is not evaluating to a function, so trying to pass an argument to it fails, thus your error message.
But, it actually has less to do with eval(), in particular. This can pop up anytime a semi-colon is omitted just prior to an IIFE or any expression starting with a (.
Adding the semi-colon, allows the runtime to know that the IIFE is separate.
The rule is that you must insert semi colons on any line that is followed by a ( (as this is how an expression can begin) in order to keep them separate . But, the better rule is to not rely on automatic semi-colon insertion at all and always put them in yourself.
This is one of the few situations in which Javascript's semicolon insertion will trip you up.
This code:
eval('console.log(0)')
(function(x){console.log(x)})(1)
Is equivalent to this code:
eval('console.log(0)')(function(x){console.log(x)})(1)
In other words, Javascript thinks that the expression eval('console.log(0)') evaluations to a function which you are trying to call with the parameter (function(x){console.log(x)}). That is obviously not what you intended, so you need semicolons at the end of your lines.
This question already has answers here:
Do you recommend using semicolons after every statement in JavaScript?
(11 answers)
Closed 6 years ago.
When executing a function in JavaScript, I've always ended my code block with a semi-colon by default, because that's what I've been taught to do. Coming from Java it felt a bit unorthodox at first, but syntax is syntax.
function semiColon(args) {
// code block here
};
or
function sloppyFunction(args) {
// code block here
}
Lately I've been seeing more and more code where the developer left the semi-colon out after functions, but the intended code still executed normally. So are they actually required? If not, why is it common practice to include them? Do they serve another purpose?
Function declarations do not need a semi-colon, though if you put a semi-colon there, it won't be harmful, it is just a redundant empty statement.
function semiColon(args) {
// code block here
};;;; // 4 empty statements
Most statements require a semi-colon, but if you leave the semi-colon out it will be inserted automatically in most cases by Automatic Semi-Colon Insertion, with caveats. In general it is easier to just always add a semi-colon after your statements, so that you, and other developers working with your code, don't have to worry about those caveats.
This code is correct:
function semiColon(args) {
// code block here
} // No need for semi-colon
var semiColon = function (args) {
// code block here
}; // Semi-colon required here
Whereas this code is wrong, but will still usually work:
function semiColon(args) {
// code block here
}; // Redundant unnecessary Empty Statement
var semiColon = function (args) {
// code block here
} // Semi-colon required here,
// but ASI will sometimes insert it for you, depending on
// the subsequent token
NO - using semicolons to end function declarations are NOT necessary in JavaScript. While they will not throw an error, they are the equivalent of using more than one semicolon to end a line of code - harmless, but unnecessary. Being superfluous, they are considered poor stylistic and programming practice.
The one exception is a function expression, e.g.
var my_function = function(a, b){ };
where you DO need the semicolon to terminate the line.
You shall not add a semicolon after a function declaration.
Because, after checking the Javascript grammar:
StatementList:
StatementListItem
StatementList
StatementListItem:
Statement
Declaration
Declaration:
HoistableDeclaration
ClassDeclaration
LexicalDeclaration
HoistableDeclaration:
FunctionDeclaration
GeneratorDeclaration
Here's the grammar production for a function:
FunctionDeclaration → HoistableDeclaration → Declaration → StatementListItem → StatementList
which proves that my former response is wrong (no need to look at the former edits, as it's wrong! ;) ).
A function xx() {} construct alone is a special case, neither — strictly speaking — a statement or an expression, and thus is NOT to be ended with a semicolon.
You only need to add a semicolon (or leave the ASI take care of it) if you're using the expression function() construct, which exists when it is part of a statement. To make it a statement you need to either have it part of a statement:
var foo = function() {};
or embedded within another expression:
(function() {})();
!function x() { ... }();
And in either cases, you need to add the semicolon at the end of the full statement, obviously.
Generally speaking, I like the python mantra "explicit is better than implicit" so when you hesitate to add a semicolon that the ASI would add otherwise, just add it.
sorry for being wrong in the first version of my answer, I'll debug some PHP code as a penitence. ☺
HTH
Looking at these articles from Mozilla's JavaScript guide:
Expressions
Statements
expressions are also considered assignment statements. In fact, in the second article one can read "any expression is also a statement". Being acquainted with other programming languages, I thought that expressions are always values, but they never cause side effects like statements would do. In other words, 7, 7 + 8, "string", etc., are expressions, because they don't change the state, but a = 7 is a statement, since a variable has now been defined (i.e. a state has changed).
Why would Mozilla not differentiate between the two in JS?
I believe you are taking the terms "expression" and "statement" too literally. "Expressions not changing any state" is a very tough requirement for a programming language.
A thought experiment: In 7 + 8 substitute 8 with a function call to
var globalVar = 0;
function my8() {
globalVar = globalVar + 1;
return 8;
}
Is 7 + my8() a statement or an expression? There is no obvious state change happing here, but still my8 performs a state change. Using the "no side-effects" definition it would be impossible to decide if 7 + my8() is a statement or an expression without analyzing the code of the my8 function. Of course it would be possible to simply prohibit any state change as part of a function call, but that is not the way of JavaScript.
In my experience most languages define "everything which returns a value" as an expression and a statement, everything else as just a statement.
To answer your question "Why would Mozilla not differentiate between the two in JS?":
I think they do, but not in the manner you expected. To consider "everything which returns a value" an expression seems to be the most practical approach.
Also there is no contradiction between a chunk of code being a statement and an expression at the same time. That is simply how Javascript and many other languages work. Of course it is always possible to draw a more strict line between those two.
Examples:
Assignments return values, so this is possible:
a = b = c = 1;
It can be written in the more obvious form:
a = (b = (c = 1));
Because of that an assignment is considered an expression (and also a statement).
On the other hand:
if (true) { };
does not return a value (in Javascript!) and therefore is no expression (but still a statement).
An expression is a code fragment that returns some value, Expression (Computer Science):
3; // 3
{}; // Object
func(); // whatever func returns, or undefined if not specified
You can combine expressions into one compound expression:
3 + 7; // 10
{}, []; // Array. Comma operator always returns result of right-most expression
A statement is the smallest valid code fragment that can be compiled or interpreted, Statement (Computer Science):
5; // valid js
You can also combine statements into compound statements:
check || func(); // valid js
{
4 + 9;
"block statement";
}
In the Mozilla documentation, a statement refers to any (compound) statement that is explicitly or implicitly terminated by semi-colon (;).
[,,[],[,[,,],,]]; // Array declaration whose reference is returned (and ignored)
// Multi-dimensional array with empty (undefined) elements
In some programming languages the above example doesn't compile or doesn't get interpreted. Other languages might not allow for the result of an expression not to be catched.
Javascript is very expressive, which is why every expression counts as a valid statement. Some statements are not expressions, like break, return, while, etc. They don't return any value, but they control the program execution flow.
Mozilla does differentiate between the two, or rather the Javascript syntax does.
The only slightly "special" about Javascript is the following:
"any expression is also a statement",
which means that at places where a statement is required in the syntax, an expression can be used directly (but not the other way around). E.g. the following is valid Javascript but invalid in many other similar languages:
if (true) "asfd"
or
foo = function(){
if (5) {
"some text here that won't do anything";
return true;
42; // always good to have that one here!
}
}
whereas statements cannot be used as expressions:
a = (if (true) 5) // does not work "unexpected token 'if'"
They used that "feature" for the strict mode specification without introducing a new keyword or syntax - if you add the expression "use strict" as the first statement in a function body, Javascript is executed in strict mode in supporting browsers.
While expressions evaluate to a value, usually, statements do not. Most statements alter control flow, expressions usually don't (although one could argue that an expression that results in an exception being thrown alters control flow, too).
In Javascript expressions form a subset of all statements.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Empty for loop - for(;;)
I just found a strange construct in the JS parser of UglifyJS (at L1045): for(;;){…}.
I assumed that an empty condition would resolve to undefined, which is converted to the boolean value false. But that's definitely not the case.
Apparently, it triggers an infinite loop. I was able to reproduce this behavior, but I have no clue why. Any (logical) explanations?
Besides: When this is possible, why doesn't while(){…} work?
That's just the definition of the semantics. A missing "test" expression is treated as an expression with the value true. Languages are made up by people, and they are at liberty to specify any behavior they like. Clearly, that behavior is something Mr. Eich likes :-)
for(;;){…} interprets an empty condition as true and while(){} is not considered as valid. As said before it's totally language dependant but described in the specification.
In the ECMA-262 language specification of JavaScript (section 12.6.3) it is defined how the behaviour of the for loop should be.
You can see from the definition that if the information around and between the semi-colons is not available, there are no conditions to leave the loop. The only way to leave the loop is by defining a test condition and optionally some start and step values.
The behaviour could be defined in a different way but that's just not how it is.
From the spec.
12.6.3 The for Statement
The production
IterationStatement : for (ExpressionNoIn(opt) ; Expression(opt) ; Expression(opt)) Statement
is evaluated as follows:
1. If ExpressionNoIn is present, then.
a. Let exprRef be the result of evaluating ExpressionNoIn.
b. Call GetValue(exprRef). (This value is not used but the call may have side-effects.)
2. Let V = empty.
3. Repeat
a. If the first Expression is present, then
i. Let testExprRef be the result of evaluating the first Expression.
ii. If ToBoolean(GetValue(testExprRef)) is false, return (normal, V, empty) .
b. Let stmt be the result of evaluating Statement.© Ecma International 2011 91
c. If stmt.value is not empty, let V = stmt.value
d. If stmt.type is break and stmt.target is in the current label set, return (normal, V, empty) .
e. If stmt.type is not continue || stmt.target is not in the current label set, then
i. If stmt is an abrupt completion, return stmt.
f. If the second Expression is present, then
i. Let incExprRef be the result of evaluating the second Expression.
ii. Call GetValue(incExprRef). (This value is not used.
Gist of this spec: for statement stops when first Expression returns "falsey" value.
Since absence of expression doesn't return false, the script will run forever (or until break statement is executed from inside the loop body).
So I just mistakenly typed something in a JS console and was surprised that it didn't give me a syntax error. My question: Why is this valid?
function foo(){
{
console.log('Valid Function');
}
}
foo();
I would assume that it would interpret the inner { ... } to be an object literal, but if that were the case the console.log wouldn't be valid... so...?
This is an anonymous code block. For example:
{var x=5; alert(x);}
Furthermore to clarify your question "to be an object literal, but if that were the case the console.log wouldn't be valid... so...?"
It is NOT an object. However, note that if you had a key: or something it could be interpreted as an object and still work, since statements which don't return anything will be interpreted as undefined.
({1:console.log('test')})
result (also prints out 'test'):
Object
1: undefined
__proto__: Object
According to this javascript 2.0 grammar:
http://www.mozilla.org/js/language/js20-2000-07/formal/parser-grammar.rtf
An object literal is defined here:
ObjectLiteral
{ } | { FieldList }
Which means it must be empty or contain a valid field list which must have a bare colon to separate the key and value.
Your block is therefore interpreted as a "Statement" which can have the braces around it.
Lots of c syntax languages have arbitrary braces to group statements, but unlike most of them, JavaScript does not limit variable scope of those variables declared in that block. This means that the extra braces do not really have much purpose, are almost never used and this is probably why you didn't expect it to work!
Braces specify a block of code. A block is a valid statement, and can appear wherever a statement is allowed. See http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf page 220.