I just spend long time digging through callbacks in promises wondering why some callbacks are not called. In the end problem was with incorrect declaration, instead of
Promise.when(null).then(function () {
var p = new Promise();
p.fail(new Error("some message"));
return p;
}).then(function () {
console.log("success");
}, function (err) {
console.log("failure");
});
I did
Promise.when(null).then(function () {
var p = new Promise();
p.fail(new Error("some message"));
return p;
}).then(function () {
console.log("success");
}), function (err) {
console.log("failure");
};
Regardless of Promise implementation details it boils down to one thing:
function(){};//throws SyntaxError
"something valid, or function call", function(){};//no error
I would like someone to explain this to me. Why first is throwing SyntaxError while latter is valid (at least in browser console)? It seems to declare anonymous function.
Same thing happens when I try
eval("function(){};//throws SyntaxError")
eval("'lala',function(){};//no error")
So can someone explain me why first is not valid while latter is ?
A statement that begins with the keyword "function" must be a valid function declaration statement. That requires a name for the function.
In an expression (or expression statement), that rule is different; no name is necessary because the function acts as a value in that context. No name is required then.
Thus this:
function myFunction() {
// ...
}
is a function declaration statement. This:
5 + function() {};
is an expression statement (a silly one, but JavaScript is ok with that). Similarly, your example that results in no error is an expression with the comma operator:
"lala", function() {};
The keyword "function" does not appear at the beginning of either of those two expressions, so the parser does not insist on a name for the function.
Your original code was not working because, as you figured out, the second function was not passed as a parameter - you put the closing paren before the function. It was causing no error because JavaScript recognized it as a function expression. Your use of the comma operator told JavaScript to expect the next statement to be an expression.
A function declaration cannot be anonymous, but a function expression can. A stand alone anonymous function looks like a function declaration that is missing an identifier to JavaScript. But, combined with an operator, JavaScript treats an anonymous function as the operator's operand expression.
The statement 'lala',function(){} consists of an expression ('lala') followed by an operator (,) followed by a function expression. This statement is similar: 0,function(){}. Promise.when(...).then(...) is also a valid expression, so Promise.when(...).then(...),function(){} works just the same.
Related
I'm trying to immediately invoke a function without using IIFE pattern (enclosing a function definition inside parentheses). Here I see two scenarios:
When a function declaration is invoked immediately: gives SyntaxError.
When a function expression is invoked immediately: executes successfully.
Example 1: gives SyntaxError
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
Example 2: Executes without any error
// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function
So, I have these doubts:
With this approach, why does it give an error for function declaration but not for function expression?
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
In your code you don't have name for the function that's the reason for syntax error. Even if you would had name it would have thrown error.
function func(){
console.log('x')
}();
The reason is the function declaration doesn't return the values of the function however when you wrap function declaration inside () it forces it be a function expression which returns a value.
In the second example the function() {console.log('Inside the function')} is considered expression because it's on RightHandSide. So it executes without an error.
Is there a way we can immediately invoke a function declaration without using IIFE pattern
You can use + which will make function declaration an expression.
+function(){
console.log('done')
}()
If you don't want to use + and () you can use new keyword
new function(){
console.log('done')
}
Extra
A very interesting question is asked by #cat in the comments. I try to answer it.There are three cases
+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5
+function(){} returns NaN
+ acts as Unary Plus here which parses the value next to it to number. As Number(function(){}) returns NaN so it also returns NaN
(+function(){return 5;})() returns Error
Usually IIFE are created using (). () are used to make a function declaration an expression + is short way for that. Now +function(){} is already an expression which returns NaN. So calling NaN will return error. The code is same as
Number(function(){})()
+function(){return 5;}() returns 5
In the above line + is used to make a statement an expression. In the above example first function is called then + is used on it to convert it to number. So the above line is same as
Number(function(){return 5}())
In the proof of statement "+ runs on after the function is called" Consider the below snippet
console.log(typeof +function(){return '5'}());
So in the above snippet you can see the returned value is string '5' but is converted to number because of +
A function declaration, like
function foo() {
}
defines (and hoists) the variable name foo as a function in the current scope. A function declaration doesn't evaluate to a value; it just does something, a bit like an if does something (rather than evaluate to a value).
You can only invoke values which are functions, eg
<somevalue>()
where somevalue is a variable name that refers to a function.
Note that function declarations require function names, because otherwise there's no variable name to assign the function to - your original
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
throws not because of the () at the end, but because of the lack of a name.
You can put parentheses at the end of a function declaration, as long as there's something inside the parentheses - but these parentheses do not call the function, they evaluate to a value:
function x() {
console.log('Inside the function');
}(console.log('some expression inside parentheses'));
The interpreter sees these as two separate statements, like
function x() {
console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));
The inside of the parentheses gets evaluated and then discarded, since it doesn't get assigned to anything.
(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)
The E in IIFE stands for expression, and without the wrapping parenthesis your function is not evaluated as an expression thus the syntax error.
creating an expression is a way of tricking the interpreter and be able to invoke the function immediatly
(function() {
console.log('Inside the function');
})();
In your example you have a function statement followed by the grouping operator, but it's syntactically incorrect for two reasons, first it doesn't have a name, and second because the grouping operator must have an expression inside it, infact if you add a valid one the error will disappear, still you won't obtain your desired result.
function foo() {
console.log('Inside the function');
}();
function foo() {
console.log('Inside the function');
}(1+2);
In order to invoke something, it has to be a function value, a declaration just declares a name, and does not evaluate to the function value itself, hence you cannot invoke it.
A declaration cannot be invoked for the above reason. You have to end up with an expression somehow, either through assignment or grouping (IIFE). So that is a no.
If you give us more context on why you would want to do that, maybe we can help with suggestions.
Not sure why you would want to do it, but:
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
Well, if for function declaration you mean using the keyword function as in:
function name() { return this.name; }
As far as I know, no. You need the extra parentheses to tell the runtime not to assign the function to a name variable, if I understand this stuff right.
Now, what you actually can do is to use Function as in:
new Function('console.log("ey there")')();
Which will execute the console.log code. No need for IIFE here. But I don't see how this could be better than an IIFE.
you can call in either below ways -
~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()
I had an IIFE like this one:
(function a() {
return "b";
}());
Executed in the console, it returns "b".
I removed the first set of parentheses, thinking that this'll make the "a" function global, but still work, and return "b":
function a() {
return "b";
}();
But it throws a SyntaxError:
Uncaught SyntaxError: Unexpected token )
Then, I tried converting the function to an expression by assigning to a variable, and it worked:
var c = function a() {
return "b";
}();
console.log(c); // prints b
Why does this happen? Why is it working as an expression but not by itself?
The second piece of code is not what it looks like.
This code looks like a function that is being immediately executed:
function a() {
return "b";
}()
But in reality, it's just a function declaration followed by an empty expression, which is not allowed:
function a() {
return "b";
}
() // not allowed - empty expression
Ben Alman explains this in his article on IIFE's:
When the parser encounters the function keyword in the global scope or
inside a function, it treats it as a function declaration (statement),
and not as a function expression, by default.
...
While parens placed after an expression indicate that the expression
is a function to be invoked, parens placed after a statement are
totally separate from the preceding statment, and are simply a
grouping operator (used as a means to control precedence of
evaluation).
The grouping operator needs to contain an expression to evaluate. By itself it's of no meaning:
() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20
In IIFE's, the outer parentheses are just a means of forcing the parser to expect an expression.
This is why the expression var c = function() { return "b"; }(); also works; it's because the parser knows to expect an expression because of the assignment to c.
Side Note
Alman also recommends against using self-invoking functions without using the outer parentheses when assigning to variables(i.e. var v = function(){...}()) because it's bad practice:
In cases where the extra “disambiguation” parens surrounding the
function expression are unnecessary (because the parser already
expects an expression), it’s still a good idea to use them when making
an assignment, as a matter of convention.
Such parens typically indicate that the function expression will be
immediately invoked, and the variable will contain the result of the
function, not the function itself. This can save someone reading your
code the trouble of having to scroll down to the bottom of what might
be a very long function expression to see if it has been invoked or
not.
Given the following:
function x() {
this.abc = 1;
function f1() {
alert(this.abc);
}.bind(this)
var f2 = function b() {
alert(this.abc);
}.bind(this);
}
What I would like is for the "this" of the outer function to be available inside the f1 and f2 functions.
Why is it that VS2013 tells me there's a syntax error with the bind(this) on function f1() ?
There's a difference between a function declaration statement and a function instantiation expression. Both involve the keyword function, but a declaration statement cannot immediately be used as a reference to a function. A function instantiation expression is part of the expression grammar, so it can be used freely in that context as a reference to a function because that's what it evaluates to.
You can of course do this:
(function a() {
}).bind(this);
though without using the return value from .bind() it's not very useful.
If the first token in a statement is function, then you've got a function declaration statement. If the first token is not function, then you've either got another sort of keyword-introduced statement (for, return, var, try, whatever), or else you've got an expression statement. In that expression (or in any expression in another context), your function instantiations are part of the expression grammar and the value can be used as a reference to a function.
Here's another way to think about the problem. Let's pretend that there is only one way to instantiate a function in JavaScript, and that's the function expression. That is, let's pretend that any use of the function keyword means to instantiate a function and return a reference to that function as it's value.
Now, thinking generally about expressions and the things that participate in expressions, the point is to compute some sort of value. When you need the value 5 as part of an expression, you put 5 in its place and that's that. By itself, 5 is a valid expression, so this is not a syntax error:
5;
What does that do, however? It does nothing. Similarly, in our make-believe JavaScript without function declaration statements,
function foo(a, b) {
return a + b;
};
would also do nothing at all. What would happen is simply that the function would be instantiated but thrown away because the value — the reference to the instantiated function — is not saved as the value of a variable or passed to some function or anything else. In this make-believe JavaScript, you'd use
var foo = function(a, b) {
return a + b;
};
all the time.
The language design does have function declaration statements, however. As a simplifying approach, the language just recognizes a statement whose first token is the keyword function as a completely different sort of statement than an expression statement that happens to contain a function instantiation. There are other ways in which the problem could have been addressed (such as the use of a different keyword), but I suspect that there'd still be confusion.
Note that there are JavaScript programmers who strongly prefer using var declarations for functions. It's a matter of style really.
This question already has answers here:
JavaScript - self-executing anonymous functions and callback
(2 answers)
Closed 9 years ago.
What is the purpose of the outer extra parentheses on the below JavaScript closure function? I have been told in other posts that they are not strictly necessary, but they're a convention to make it clear that the result of the function is being passed, not the function itself. The below quote from http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
, however, conflicts. Which is correct?
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.
(function () {
// ... all vars and functions are in this scope only
// still maintains access to all globals
}());
I think that different engines have different ways of interpreting
function(){...}();
so the most popular and accepted way to make it clear, to all engines, is to group the code in parentheses.
(function(){...}());
At the same time, what you quoted makes a very interesting point. A function expression might go:
var f = function() {...}
Whereas a function declaration looks like:
function f() {...}
You see how it's easy/convenient for the parser to tell the difference by looking at the first token?
IF TOKEN1 EQ "function": FXN DECLARATION
ELSE: FXN EXPRESSION
But it wouldn't make sense for your (immediately-invoked) function to be a function declaration (it's not going to be re-used, you don't want to have it hoisted, or in the namespace, etc.) so adding some innocuous parentheses is a good way of indicating that it's a function expression.
First of all, I must clear up:
(function () {
}());
is equivalent for
(function () {
})();
and also for (Backbone.js uses it)
(function(){
}).call(this);
Second, if you're going to use it that way, then it's not an anonymous/closure function. its Immediately-Invoked Function expression
it would act as a closure (because it won't be immediately-invoked) if you assign its returned context to a variable. This kinda useful if you need a static class (when properties and methods could be accessed without instantiation). For example:
var stuff = (function(){
// AGAIN: its not an IIFE in this case
function foo() // <- public method
{
alert('Jeeez');
}
return {
foo : foo,
}
})();
stuff.foo(); //Alerts Jeeez
What is the purpose of the outer extra parentheses on the below
JavaScript closure function?
The purpose isn't usual and quite strange - its all about function arguments.
For example,
(function(window, document){ // <- you see this? 2 "arguments"
alert(arguments.length); // 0!
})();
but if we pass them to that outer parentheses
(function(/* So its not for arguments */ ){
alert(arguments.length); // 2
})(window, document); // <- Instead we pass arguments here
The extra surrounding parentheses disambiguate a function expression from a regular function declaration.
Though the extra parentheses are standard practice, the same thing can be achieved by doing this instead:
void function() {
// do stuff
}();
Or, even:
+function() {
// do stuff
}();
Though, out of these two alternatives, I prefer the void notation because in most cases we don't really care about the return value of an immediate invocation.
Other places where the parentheses aren't required is when an expression is expected:
setTimeout(function() {
return function() {
alert('hello');
}
}(), 1000);
They are necessary because the parser goes in the function declaration mode when it sees
function
in a statement context.
After function token, it is expecting a name for the function because a function declaration must include a name for the function. But instead of a name it sees ( instead, so it's a syntax error.
I think, it could backtrack and unambiguously just treat it as a function expression but it doesn't.
var module = XXX
In the above, XXX is in expression context, if a function appears there, it is treated as a start of a function expression. Function expressions don't have to have
a name for the function, so it's not a syntax error to have ( appear right after function.
So you can write:
var module = function(){}();
But not
function(){}()
You can use many tricks to make the above an expression:
(XXX)
!XXX
~XXX
+XXX
//This doesn't work however:
{YYY} //the braces are delimiting a block, and inside block you start in
//a statement context
XXX is in expression context because it's enclosed by parenthesis or is following a unary operator, therefore any function substituted for XXX is a function expression.
Why does this return a syntax error:
function(foo){console.log(foo)}
I'd expect this to return the value of the function, hence return itself, and not assign it to anything, but i get a "SyntaxError: Unexpected token ("
but this works:
(function(foo){console.log(foo)})
Please explain what purpose those wrapping parenthesis serve. I've been told that parens are used to "increase readability" but in this case there definitely is more purpose served.
Can you please go into further detail about use about () ? Say you were to translate that line of code to prose, what would the () read like? I am trying as well to describe this concept to other people, and need to transmit its meaning so that everybody can understand it. The question i'm trying to answer, is what do the ()'s mean? Do they have a semantic value, and what is it?
Your first example is a function declaration. It doesn't have an identifier, which is a syntax error. Here's the grammar for a function declaration (notice that Identifier is not optional):
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
By wrapping it in parentheses you turn it into a function expression (an anonymous one). You could execute it by adding a pair of invoking parentheses after:
(function(foo){console.log(foo)})("hello"); //Will log 'hello'
Here's the gammar for a function expression (now the identifier is optional):
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
How the parentheses turn a function declaration into a function expression
In this case, the parentheses are parsed as a "grouping operator". The grammar for the grouping operator is as follows:
PrimaryExpression :
( Expression )
The grouping operator can only contain an expression, so your function is parsed as an expression rather than a declaration (obviously, in your exact example, the function can't be a declaration since it doesn't have an identifier).
This is because without the (), the function(){} line is a function declaration, while with the () is an expression.
function declarations are a strange beasts, they made available everywhere in the scope they are defined in before code execution, so snippets like this works:
foo();
function foo() { console.log('foo'); }