On Jan 1, 2011, at 5:00 AM, Dmitry A. Soshnikov wrote:
> On 01.01.2011 2:43, fernando trasvina wrote:
>> Hi. very nice explanation but what i don't fully understand is why the
>> grouping operator makes the parenthesis following the function declaration
>> work as call.
>>
>> (function(x){alert(x)}(1));
>>
>> why this is not treated the same way as:
>>
>> function(x){}(1);
>>
>
> Because inside the grouping operator () there can be only an _expression_. No
> matter in which way you place a function there (with a call or without it) --
> it's treated as FE (function expression). I.e. everything that is placed
> inside the grouping operator is an expression.
>
> (1); // grouping operator with expression 1
> ("test"); // with expression "test"
> (function () {}); // with a functional expression
>
> So in case when you have the following construction:
>
> (function (x) {alert(x)})(1);
>
> We have:
>
> 1. A grouping operator with a function(al) expression inside. It's exactly
> the sign to the interpreter that this _something inside the grouping
> operator_ should be _evaluated_ during the _execution_. I.e. we have a
> function definition there. And this function definition is provided during
> the runtime.
>
> 2. Applying (1) on the result of which is returned by the grouping operator
> (i.e. our just created function). And notice, this is already exactly the
> _call_ -- (1), but not a grouping operator as it was with a function
> declaration (FD).
>
> Since FDs are created on entering the context stage (i.e. before the runtime
> execution), obviously the following (1) _cannot_ be treated as a _call_.
> Therefore, the parser considers theses as two constructions: FD and a the
> following grouping operator:
>
> function foo(x){alert(x)}(1); // not a call, but syntactically correct
>
>
> Backing to FEs. When you have the following construction:
>
> (function (x) {alert(x)}(1));
>
> Again it's the sign to the interpreter that _something_ inside the grouping
> operator should happen (evaluated) at runtime. And what is inside it doesn't
> matter much at the stage of the parsing. When at runtime the interpreter
> reaches this line, it just eval(uate)s the expression -- were the expression
> is again -- creating the function and calling it.
Nice. thx. i read a lil bit after reading this and i think the explanation
could be improved by including the following areas (not in this particular form
but this helped me on clearing doubts):
Program:
Statement
FunctionDeclaration
Statement:
Block
VariableStatement
EmptyStatement
ExpressionStatement
IfStatement
IterationStatement
ContinueStatement
BreakStatement
ReturnStatement
WithStatement
LabelledStatement
SwitchStatement
ThrowStatement
TryStatement
DebuggerStatement
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
notice the optional clause on Identifier for the FunctionExpression,
FunctionDeclaration requires Identifier
ExpressionStatement :
[lookahead ∉ {{, function}] Expression ;
Expression: (there are too many but you can see them in appendix 3 of ECMA-262,
FunctionExpression is not directly listed but you can see it on Appendix 5 of
ECMA-262)
Note: This excludes Block and FunctionExpression
So with this rules at the program level and every place where StatementList is
used you will always get a FunctionDeclaration.
FunctionDeclarations are never callable, this is the rule for a CallExpression
CallExpression :
MemberExpression Arguments
CallExpression Arguments
CallExpression [ Expression ]
CallExpression . IdentifierName
A FunctionDeclaration is not a MemberExpression neither a CallExpression.
Statement is a not returning construct in the language, it does not "return"
anything so no CallExpression can be formed.
note that GroupingOperator is a PrimaryExpression not a Statement so it does
"returns" something.
you say this already but maybe give it more importance.
GroupingOperator
PrimaryExpression:
...
(Expression)
This means that everything inside () is treated as an expression and when you
put function x(){} inside its parsed as FunctionExpression never as
FunctionDeclaration
hope it helps, it helped me to understand it better.
Also i would like to give credit and recommend the way Jose Antonio Perez wrote
the explanation
Happy new year ;)
Remember, a A FunctionDeclaration's function is added to the
VariableEnvironment in Variable Instantiation. It is not and cannot be an
ExpressionStatement.
An FunctionExpression is an ExpressionStatement; it is not bound to the VE
(VariableEnvironment) on entering an execution context. A FunctionExpression is
disabiguated from a FunctionDeclaration by the fact that an ExpressionStatement
can't start with the `function` keyword.
When `f` is called, a VariableEnvironment (VE) is created. For each
FunctionDeclaration in the FunctionBody of `f` the Identifier of that
FD is added to the VE.
The point that Dmitry is trying to explain has nothing to do with the running,
is a topic within the field of parsing. The grammar that you can see in
specification is equivalent to
SourceElements: ( Statement | FunctionDeclaration )+
Program: SourceElements?
FunctionBody: SourceElements?
FunctionDeclaration : function Identifier (FormalParameterList?){FunctionBody}
The source will be divided into Statements and FunctionDeclarations, and a
FunctionDeclaration ends in a "}", therefore the arguments of a hypothetical
call haven't connection with "their function", the parser will place they in
the following SourceElement, an ExpressionStatement.
i just copied his post here.
Lastly.
I would like to call everyone to not give answers like because its a Syntax
Error, or Because that is not allowed.
please explain as necessary so people interested on the topic get all the
relevant information they want (need) if you don't want too well just don't say
anything but misleading explanations or getting defensive over a mistake like a
typo or focusing on irrelevant details will not lead us anywhere and people
will not come to this list to read another fight.
This is of everyone, i got into a pointless discussion here too and i hope i
never get into one again, please lets focus on improving the community.
>
> Notice though, that there is one subtle case related with these two similar
> forms.
>
> // first function
> var foo = function () {
> return true;
> }
>
> // second function
> (function (x) {return x})(1);
Here the trick is just seeing this as the parser does.
var foo = FunctionExpression Arguments Arguments
var foo = CallExpression Arguments
var foo = CallExpression
so at the end you can rewrite the code as the following.
var foo = function () { return true }(function (x) {return x})(1);
Boolean is not callable.
same as: (true)(1);
>
> The example above has an error (try to explain why). Thus, the following
> example doesn't:
>
> // first function
> var foo = function () {
> return true;
> }
>
> // second function
> (function (x) {return x}(1));
var foo = FunctionExpression Arguments
Arguments is an ArgumentsList with a single Argument, the result of
(FunctionExpression Arguments)
FunctionExpression Arguments is a CallExpression
in this case returns 1;
so at the end you can rewrite the code as the following.
var foo = function () { return true }(1);
>
> Also, try to explain why. Though, the topic of the answer isn't related with
> the discussed topic. How the answer will change if the `foo` function will
> return an object of the other kind?
return a Function instance because its the only callable object.
there is another way to "fix" it. just finish the statement after asigning foo.
// first function
var foo = function () {
return true;
}; // <-- here
// second function
(function (x) {return x})(1);
Maybe this examples should also be included on your article as possible gotchas.
>
> Dmitry.
>
>> On Dec 31, 2010, at 7:46 AM, Dmitry A. Soshnikov wrote:
>>
>>> Just for those who don't use Twitter. I've just edited my
>>> "ES3.Ch5.Functions" article in respect of explanation the "surrounding
>>> parentheses". The thing is, that almost _all_ explanations (in books,
>>> articles, etc) were at least very incomplete (and even wrong).
>>>
>>> So, why does this code produces a SyntaxError:
>>>
>>> function () {
>>> ...
>>> }()
>>>
>>> // or with name
>>>
>>> function foo() {
>>> ...
>>> }();
>>>
>>> Try to provide as much complete explanation as possible. Also try to answer
>>> without cheating ;) The correct and full explanation is here:
>>> http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses
>>>
>>> Dmitry.
>>>
>>> P.S.: Happy New Year!
>>>
>>> --
>>> To view archived discussions from the original JSMentors Mailman list:
>>> http://www.mail-archive.com/[email protected]/
>>>
>>> To search via a non-Google archive, visit here:
>>> http://www.mail-archive.com/[email protected]/
>>>
>>> To unsubscribe from this group, send email to
>>> [email protected]
>
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/[email protected]/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/[email protected]/
>
> To unsubscribe from this group, send email to
> [email protected]
--
To view archived discussions from the original JSMentors Mailman list:
http://www.mail-archive.com/[email protected]/
To search via a non-Google archive, visit here:
http://www.mail-archive.com/[email protected]/
To unsubscribe from this group, send email to
[email protected]