From: Garrett Smith on 20 Apr 2010 18:38 Johannes Baagoe wrote: > Stefan Weiss : >> Johannes Baagoe : > [...] > You are right, I can't. If I want to define 21! inline using neither > named function expressions nor function declarations, the best I have > come up with is > > ((function() { > return fact = function(n) {return n > 0 ? n * fact(n - 1) : 1;}; > }())(21)); > > which is hardly a model of legibility. > Or design. Syntactially, it could do without the excess grouping operator and certainly can do without creating a global identifier within a function. However if the goal is to write a factorial function, it would be best to focus on that; so changing the syntax would miss the point. A factorial function should consider input > 170, i.e. throw a RangeError, utilize a user-defined `BigNumber`, etc. > So there may legitimate uses for named function expressions after all. > The trouble is that their formal definition is so badly ambiguous > that I immediately object on aesthetic if not on sound theoretical > grounds, but I admit that if the implementations always get it right, > it becomes little more than a matter of taste. (Of course, if MDC > doesn't lie, some implementations *don't* get it right, which gives > rather more weight to my theoretical pretexts.) > The formal grammar for FunctionExpression, with optional Identifier, can be easily understood. MDC published misinformation there, unfortunately. I do not know why you cannot see that; I have explained it well enough twice now. If there is any part of my explanation that was confusing, or that you thought was wrong, please specify. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Johannes Baagoe on 20 Apr 2010 18:39 Garrett Smith : > Then what is wrong with an implementation treating a FunctionExpression > as a Function Definition? Nothing at all, a FunctionExpression *is* a Function Definition. > And if the answer is nothing (which is the correct answer) then why > insist Microsoft got that wrong? Apparently, MDC got at least *its* wording wrong : what "Some JavaScript engines, not including SpiderMonkey" *may* do wrong (I can't figure out whether it is true) is not to "incorrectly treat any function expression with a name as a function definition", but to incorrectly treat any function expression with a name as a function *declaration*. MDC's bone of contention is this: if (0) { function zero() { document.writeln("This is zero."); } } According to MDC, we have a function *expression*, which means that zero is undefined unless defined elsewhere. js bears that out. At least V8 (Chrome) considers it a function *declaration*, i.e., zero is a function. I am not sure myself - understanding the specs requires more than I am willing to spend on the problem, after having given it a try both in 3rd and 5th ed. If someone can explain it in plain words to an ordinarily stupid programmer like me, I shall be very grateful. In any case, someone is wrong. It may be Microsoft (that was Jorge's assumption, I have no personal opinion on the subject, not being a Microsoft costumer), in which case Chrome is just as wrong. It may be Mozilla. If I understood the specs, I would know, but I don't. But for exactly that reason, I think whoever is wrong has at least a "lame excuse", lamer, to be sure, in the case of people who get paid to get it right than in mine. Namely that the specs are horrible: FunctionDeclaration : function Identifier ( FormalParameterList opt ) { FunctionBody } FunctionExpression : function Identifier opt ( FormalParameterList opt ) { FunctionBody } mean that when the FunctionExpression has its optionalIdentifier, there is nothing in its syntax to differentiate it from a FunctionDeclaration. That is a syntactic ambiguity of about the worst sort imaginable. How is it resolved? Well... happy reading of the specs :) On the other hand, if the "Identifier opt" part in the definition of FunctionExpression were removed, there would be no ambiguity at all. Which explains my perhaps excessive dislike of named function expressions. -- Johannes
From: Johannes Baagoe on 20 Apr 2010 20:06 Jorge : [named function expressions] > 1.- They're not used much due to the named function expressions BUG > in Microsoft's Internet Explorers (in ALL of them). That may the case for many people, but it has nothing whatsoever to do with *my* dislike of named function expressions. I hate them because their syntax sucks. Bugs in Microsoft products are of no concern to me, since I don't use them. > 2.- The function's name is defined inside the function, where it's > safer (and faster too) than in the enclosing scope. Where that is a concern, I use a function declaration. > 3.- (function functionName () {}).name is === "functionName". > So you can get it from the outside, if you ever need to. I don't, since I don't use named function expressions. If I want to use a function more than once, either I declare it, or I assign its expression to a variable. > Plus a 4th point of my own: > 4.- [...] Microsoft has been careful not to fix ever, have had the > (intended) effect [...] Microsoft's own interests, [...] Make no > mistakes: it's not by coincidence. I couldn't care less about Microsoft. On the other hand, I don't speculate on nefarious motives and intents, either. -- Johannes
From: Garrett Smith on 20 Apr 2010 20:18 Johannes Baagoe wrote: > Garrett Smith : > >> Then what is wrong with an implementation treating a FunctionExpression >> as a Function Definition? > > Nothing at all, a FunctionExpression *is* a Function Definition. > >> And if the answer is nothing (which is the correct answer) then why >> insist Microsoft got that wrong? > > Apparently, MDC got at least *its* wording wrong : what "Some > JavaScript engines, not including SpiderMonkey" *may* do wrong (I > can't figure out whether it is true) is not to "incorrectly treat > any function expression with a name as a function definition", > but to incorrectly treat any function expression with a name as a > function *declaration*. > > MDC's bone of contention is this: > > if (0) { > function zero() { > document.writeln("This is zero."); > } > } > > According to MDC, we have a function *expression*, which means that > zero is undefined unless defined elsewhere. js bears that out. > Actually that is a FunctionStatement, an allowed syntax extension. The documentation there uses "function statement" in two ways: 1) Parenthetically, as an alternative for FunctionDeclaration (wrong) 2) To mean the syntax extension "FunctionDeclaration" (right) <https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Functions#section_15> > At least V8 (Chrome) considers it a function *declaration*, i.e., > zero is a function. > The function declaration (function statement) Edit section > I am not sure myself - understanding the specs requires more than > I am willing to spend on the problem, after having given it a try > both in 3rd and 5th ed. If someone can explain it in plain words to > an ordinarily stupid programmer like me, I shall be very grateful. > > In any case, someone is wrong. It may be Microsoft (that was Jorge's > assumption, I have no personal opinion on the subject, not being > a Microsoft costumer), in which case Chrome is just as wrong. It > may be Mozilla. If I understood the specs, I would know, but I don't. > Microsoft has a well known bug with named function expressions. There are many posts in the archives, but Juriy's article explains it in one place (that is also linked from the FAQ). > But for exactly that reason, I think whoever is wrong has at least a > "lame excuse", lamer, to be sure, in the case of people who get paid > to get it right than in mine. Namely that the specs are horrible: > > FunctionDeclaration : > function Identifier ( FormalParameterList opt ) { FunctionBody } > FunctionExpression : > function Identifier opt ( FormalParameterList opt ) { FunctionBody } > > mean that when the FunctionExpression has its optionalIdentifier, there > is nothing in its syntax to differentiate it from a FunctionDeclaration. > That is a syntactic ambiguity of about the worst sort imaginable. > Not at all. The ECMAScript specification has no provision for FunctionDeclaration to appear where a Statement may appear. However, an ExpressionStatement may appear where a Statement is allowed. A FunctionExpression is an ExpressionStatement. Therefore, a FunctionExpression may appear where a Statement is allowed. > How is it resolved? Well... happy reading of the specs :) > | Statement | Block | VariableStatement | EmptyStatement | ExpressionStatement | IfStatement | IterationStatement | ContinueStatement | BreakStatement | ReturnStatement | WithStatement | LabelledStatement | SwitchStatement | ThrowStatement | TryStatement FunctionDeclaration is not on that list. ExpressionStatement is. ExpressionStatement ExpressionStatement [lookahead {{, function}] Expression An ExpressionStatement can't start with "{" because that would create ambiguity to determine if it is a block or an object literal and it can't start with "function" because that could it ambiguous with a FunctionDeclaration (s 12.4). A MemberExpression is a Left-Hand-Side Expression. MemberExpression : PrimaryExpression FunctionExpression MemberExpression [ Expression ] MemberExpression . Identifier new MemberExpression Arguments A FunctionExpression is an MemberExpression. A FunctionDeclaration is not an Expression; it is a SourceElement. Spidermonkey adds FunctionStatement. JScript adds FunctionDeclaration, however, JScript also has JScriptFunction. In JScript, upon entering an execution context, each FunctionExpression's identifier and each FunctionDeclaration's identifier, and all identifiers in a JScript FunctionBindingList of a JScriptFunction are added as properties of the containing Variable object. | For each FunctionDeclaration or FunctionExpression in the code, in | source text order, do one of the following depending upon the form of | the FunctionDeclaration or FunctionExpression: | * If the production is of the form | FunctionDeclaration : function ( FormalParameterListopt ) | { FunctionBody } | or | FunctionExpression : function ( FormalParameterListopt ) | { FunctionBody } | | do nothing. | * If the production is of the form | FunctionDeclaration : function Identifier ( FormalParameterListopt ) | { FunctionBody } | or FunctionExpression : function Identifier ( FormalParameterListopt ) { FunctionBody } create a property of the variable object whose name is the Identifier in the FunctionDeclaration or FunctionExpression, whose value is the result returned by creating a Function object as described in 13, and whose attributes are determined by the type of code. If the variable object already has a property with this name, replace its value and attributes. Semantically, this step must follow the creation of FormalParameterList properties. If the production is of the form FunctionDeclaration : JScriptFunction or FunctionExpression : JScriptFunction perform the following steps: 1. Let func be the result returned by creating a Function object as described in 13. 2. Process the FunctionBindingList element of the JScriptFunction as described in 13 and using func and the attributes for the current type of code as processing arguments. [...] -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Stefan Weiss on 20 Apr 2010 20:32
On 21/04/10 02:06, VK wrote: > On Apr 21, 2:46 am, VK <schools_r...(a)yahoo.com> wrote: >> This IE's behavior is won't-fix anyway, so not a bug but a peculiarity >> (aka a feature), so interesting for a theoretical discussion only. That they've decided not to fix it doesn't make it any less a bug. You can call it a feature, if you want, but don't get upset when others don't agree with you. >> From this theoretical point of view I'd like to grasp - and be >> merciful on my weak mind - why >> var bar = (function foo(){/*whatever*/}()) >> window.alert(typeof foo); // function >> pisses some Mozilla people off for year while >> var a = (b = 1); >> window.alert(a); >> window.alert(b); // 1 >> keeps them relaxed? Because one works as specified, and the other doesn't. > Or for that matter: > > <script type="text/javascript"> > var a = ( (b = 1) + 1 ); > window.alert(a); // 2 > window.alert(b); // 1 > > function f() { > var c = ( (d = 1) + 1 ); > } > > f(); > > window.alert(typeof c); // undefined > window.alert(typeof d); // number > </script> > > and it is OK but FunctionExpression is a matter of some silly rwar for > years? I mean since when (expression parenthesis) became contextually > dependent visibility scope regulators in JavaScript? Did I miss some > important events? You may have missed what happens when you assign to an undeclared identifier: it becomes a property of the global object. Are you asking why 'c' was kept local and 'd' wasn't, or are you asking why people think that's a good thing? -- stefan |