From: Garrett Smith on
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
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
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
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
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/