From: Garrett Smith on 20 Apr 2010 20:39 Garrett Smith wrote: > Johannes Baagoe wrote: >> Garrett Smith : >> [...] > | or FunctionExpression : function Identifier ( > FormalParameterListopt ) { FunctionBody } create a property of the > variable object whose name > is the Identifier in the FunctionDeclaration or FunctionExpression, Sorry about the formatting. I apparently hit Thunderbird's "send" keyboard shortcut. I do not recall what that is, but seem to have hit it while typing, 'cause it got sent. The full production for JScriptFunction is found in the document MS-ES3.pdf, linked from the Resources section of the FAQ. [snip] -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Garrett Smith on 20 Apr 2010 23:41 RobG wrote: > On Apr 20, 3:05 pm, nick <nick...(a)fastmail.fm> wrote: >> On Apr 19, 9:55 pm, Johannes Baagoe <baa...(a)baagoe.com> wrote: >> [...] >> "Some JavaScript engines, not including SpiderMonkey, incorrectly >> treat any function expression with a name as a function definition" > > That article seems quite confused, e.g. > > | A function declaration also creates a variable > | with the same name as the function name. Thus, > | unlike those defined by function expressions, > | functions defined by function declarations can be > | accessed by their name in the scope they were > | defined in: > | > | 1. function x() {} > | 2. alert(x); // outputs x serialized into a string > That output depends on the behavior of host method `alert`, and the implementation-dependent behavior for Function.prototype.toString. > Which is may well be confusing as function expressions exhibit exactly > the same behaviour: > > var x = function(){}; > alert(x); // outputs x serialized into a string > That bug was knowingly and deliberately included in ECMAScript 262, edition 5. The bug is that the spec says Function.prototype.toString must return a FunctionDeclaration. Instead, implementations mostly, for user-defined functions, return a representation of a function, either as a FunctionExpression or a FunctionDeclaration. When a function has no identifier, it cannot be considered as a production for FunctionDeclaration and so the string "function(){}", as returned by implementations, is not a representation of a FunctionDeclaraton. I proposed the specification to change to allow FunctionExpression. I did not see a thoughtful, reasonable response to that; EOD[1]. [...] > > The article seems to be a collection of thoughts about functions, > rather than a structured tutorial about functions. I would not > recommend it to anyone trying to learn ECMAScript. > It needs some organizational work and technical corrections. [1]<https://mail.mozilla.org/pipermail/es-discuss/2009-September/009820.html> -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Stefan Weiss on 22 Apr 2010 10:39 On 22/04/10 15:53, VK wrote: > On Apr 22, 5:16 pm, Stefan Weiss <krewech...(a)gmail.com> wrote: >> The "f" identifier is only visible inside the function *body*, which is >> consistent with JS's function-as-scope paradigm. > > See my last question to Mr.Cornford. I don't understand the point of that question, so I can't answer it. Good thing you asked someone else ;-) > Outer functions are visible to > Global so can be handled; nested functions are visible to the outer > function so can be handled. Named FunctionExpressions are visible > to...? Again, from top to bottom point of view. Asking where an expression is visible doesn't make sense. The optional identifier of a FunctionExpression is visible in its function body (I think I already explained that). Technically speaking, since you asked how the engine can see it, the identifier becomes a property of the execution context's variable object. This is all specified clearly enough, and Garrett has even quoted the relevant passage of the specs in this very thread. > P.S. OT. There are a lot of "features" of the kind we have to live > with. Real bugs get fixed, believe you me. That made me smile :) "Real bug" or "feature" is in the eye of the beholder. Software vendors can officially define which is which, and when that definition clashes with their users' expectations often enough, people tend to get angry. This specific vendor is not amenable to criticism from developers. What you perceive as Microsoft hate is just the logical consequence. > How do you like that > "feature" of Fx for instance (now we can successfully address > properties of undefined, cool): > > <html> > <head> > <title></title> > <meta http-equiv="Content-Type" > content="text/html; charset=iso-8859-1"> > <script type="text/javascript"> > window.onload = function() { > window.alert(typeof document.all); // undefined > window.alert(document.all.test) // [object HTMLParagraphElement] That's your own fault for not using a proper doctype. Careless coding is the one and only reason why compatibility hacks like this had to be introduced in otherwise (relatively) standards compliant browsers. Do us a favor and 1) use a doctype in your HTML documents 2) do _not_ use document.all -- stefan
From: Garrett Smith on 22 Apr 2010 13:00 VK wrote: > On Apr 22, 2:43 pm, Johannes Baagoe <baa...(a)baagoe.com> wrote: >> But my reasons for doing so has nothing to do with that bug I didn't >> even know existed. It because I like to think of >> >> function f() {/*...*/} >> >> as a mere shorthand, a.k.a. "syntactical sugar", for >> >> var f = function() {/*...*/}; >> >> (I suspect that this is not true > > it is not for IE at least > > , and I expect to be told in elaborate >> detail why it only shows a lamentable ignorance of the specs, for >> which I shall be duly grateful. > > It was explained in my other post in this thread: > http://groups.google.com/group/comp.lang.javascript/msg/eaa3f218c6babea4 > The explanation you posted there is incorrect. A FunctionDeclaration is created upon "Entering an Execution Context". A FunctionExpression is evaluated in order of Statements being evaluated. You can read "Entering an Execution Context" from ECMA-262 and also this: <http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/#entering-the-execution-context> A short exposition of the difference shows that in testDec, the FunctionDeclaration is available to Statements before it appears in source order. A FunctionDeclaration is created upon Entering an Execution Context /* Returns a function */ function testDec() { return f; function f() {/*...*/} } In contrast, FunctionExpression is evaluated in order of Statements being evaluated, so the value is not available prior to being evaluated in source order. /* Returns undefined. function testExp() { return f; var f = function() {}; } In some cases you want FunctionDeclaration, in other cases, FuncitonExpression is more appropriate. var b; if(window.special) { b = function() { alert('special'); }; } else { b = function() { alert('not special'); }; } There are various patterns that use closures. [...] -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Garrett Smith on 22 Apr 2010 17:14
VK wrote: >>> It was explained in my other post in this thread: >>> http://groups.google.com/group/comp.lang.javascript/msg/eaa3f218c6babea4 >> The explanation you posted there is incorrect. > > Sorry to disagree, but it is. I was talking about a named > FunctionExpression in IE, not about FunctionExpression overall as per > ECMA-262 > OK. I saw: | (function foo() { /*...*/ })() | | is equivalent (with some subtle details) to: | | function foo() { /*...*/ }; | foo(); but I now realize that just before that was the line: | In IE: That is arguably correct. The part that is arguable is if the details are subtle or not. In JScript, the production: | (function foo() { /*...*/ })() Results in the creation of both a FunctionExpression *and* a FunctionDeclaration. This behavior is a deviation that is documented in MS-ES3 pdf (linked from the FAQ). Other interesting related deviations documented therein include "Entering an Execution Context" and the `JScriptFunction` production. >> A FunctionDeclaration is created upon "Entering an Execution Context". A >> FunctionExpression is evaluated in order of Statements being evaluated. > > Again, I have a very little interest in what is written in ECMA-262 of Yes I know. The specification is of interest for those who want to understand the language. > any edition yet I am greatly interested in my script behavior for > 60%-90% of my visitors per regions. In IE: > I prefer to adhere the pertinent standard features, expect nothing more than is stated. Understanding how a program can be expected to behave is valuable. When the program works, but as a result of using nonstandard quirks, it has potential to break later on. When taking on a piece of legacy code or when reviewing a peer's code, finding where the code relies on nonstandard quirks helps find weaknesses in the code. Of course, a program's weaknesses can include more than reliance on nonstandard features; that is only one potential weakness. Specifications do not instruct one how to design a program (and things like WebIDL seem to go to great lengths to encourage some atrociously bad design). Regarding the statistical criteria: 90% means that one out of ten won't get the right script behavior. 60% is just over half. Ouch! > function demo() { > return [bar, foo]; > var foo = function bar(){}; > } > > var v = demo(); > > window.alert(v[0]); // "function bar(){}" > window.alert(v[1]); // "undefined" > > thus: > > function demo() { > return [bar, foo]; > var foo = function bar(){}; > } > Expected output: ReferenceError - bar is undefined. > equals to > > function demo() { > return [bar, foo]; > var foo = bar; > function bar(){}; > } > Expected output: Array containing 'bar' reference and value undefined. [bar, undefined] The two are not equivalent. > as it was explained earlier. Calling the first `demo` function: Upon entering the execution context, Variable Instantiation is performed, adding `foo` the VO as a property with value `undefined`. Variable Instantiation completed, Statements are evaluated. The first statement, a ReturnStatement, is evaluated. The ReturnStatement contains an ArrayLiteral expression. Evaluating the ArrayLiteral, the identifiers `foo` and `bar` must be resolved. The identifier `foo` is resolved on the VO, however `bar` cannot be resolved to an identifier and so a ReferenceError is produced. The function throws the ReferenceError, completing abruptly. Calling the second `demo` function: Upon entering the execution context, *FunctionDeclaration* `bar` is added to the VO and given a value of that Function object created by the source which follows the identifier. Next, variable `foo` is added to the VO and given the value `undefined`. Variable Instantiation completed, Statements are evaluated. As in the previous example, the first statement, a ReturnStatement, is evaluated. Here again, an ArrayLiteral expression results in the creation of an array where identifiers `foo` and `bar` must be resolved. Both values are resolved and added to the Array. The ReturnStatement complete, the function completes, returning the reference to the Array to the caller. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/ |