And presumably with the assumption that each single example is in
isolation. And preferably with some effort having been put in with
regard to providing a readable presentation.
> 1)if (!("a" in window)) {
> var a = 1;}
>
> alert(a);
The expected output is 'undefined', as the - a - variable is declared
but never assigned a value (because being declared the - "a" in window
- is true, at least it would have been guaranteed to be true of - "a"
in this - had been used, the window <-> ECMAScript global object
relationship being a little more involved).
> 2)var a = 1,
> b = function a(x) {
> x && a(--x);
> };
> alert(a);
The expected output is '1'. The JScript named function expression bug
came into play but the assignment of 1 to - a - happened after
variable instantiation so the reference to the extra function has been
replaced.
> 3)
> function a(x) {
> return x * 2;}
>
> var a;
> alert(a);
The expected output is 'function a(x)( return x * 2;}', but possibly
with formatting.
> 4)
> function b(x, y, a) {
> arguments[2] = 10;
> alert(a);}
>
> b(1, 2, 3);
The expected output is '10'.
> 5)
> function a() {
> alert(this);}
>
> a.call(null);
The expected output is the string representation of the global object,
which is implementation dependent.
> The code was copied (without doublechecking)
Or much thought going into presentation.
> fromhttp://dmitry.baranovskiy.com/
Richard.
[...]
>> 4)
>> function b(x, y, a) {
>> arguments[2] = 10;
>> alert(a);}
>>
>> b(1, 2, 3);
>
> The expected output is '10'.
Watch out for old versions Safari <= 2.0 (elerts "3").
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
> [...]
> The JScript named function expression bug
> came into play but the assignment of 1 to - a - happened after
> variable instantiation so the reference to the extra function has been
> replaced.
>
JScript NFE's bug doesn't matter in here, anyway result will be [1] -
with correct implementation of NFE or not.
> [...]
> The expected output is the string representation of the global object,
> which is implementation dependent.
>
Yeah, but e.g. Google Chrome seems to distinguish real [undefined]
value and [not passed] parameter:
var getClass = Object.prototype.toString;
alert(getClass.call()); // [object Object]
alert(getClass.call(undefined)); // [object builtins]
alert(getClass.call(null)); // [object builtins]
alert(getClass.call(this)); // [object global]
First three calls should use the global object as [thisArg] (by
15.3.4.4, ES-3), and the fours one - is real global object passed (in
code of the global context), but as we can see Chrome treats this
cases differently.
/ds
function f () { return 1; }
if (true) {
function f () { return 2; }
} else {
function f () { return 3; }
}
alert(f()); // ?
--
Jorge.
> function f () { return 1; }
>
> if (true) {
> function f () { return 2; }} else {
>
> function f () { return 3; }
>
> }
>
> alert(f()); // ?
> [...]
>
By the spec, btw, this cases are *not correct* at all. In block can be
only *statments* (not expressions as we can thinks that it's function
expression). The only way that expression can appear in block is
Expression Statement which *cannot* starts from open bracket "{" and
"function" keyword. So theoretically, this code is incorrect.
But indeed, as specification allows *syntax extension* (16, ES-3) no
one implementation throws exception there but handles that code, but -
every by it's own. Spidermonkey's extension called *Function
Statement* - such a combination of (Function Declaration + Function
Expression) - this functions will be created in "runtime" (on parse
code level) but not on entering execution context like Function
Declarations are. Other implementations just create here simple FD
(and take the last one).
So,
FF - 2;
Other - 3
I know :-) What does IE do ?
--
Jorge.
>
> [...]
>
> I know :-) What does IE do ?
>
IE does [3] as treats this function as FD.
As it does with FEs too :-)
--
Jorge.
>[...]
> As it does with FEs too :-)
> [...]
>
Only for named FEs ;)
var referenceToNFE = function testNFE() {
alert([
arguments.callee === referenceToNFE,
arguments.callee === testNFE
]);
};
And in the next one?
referenceToNFE(); // [?, ?]
testNFE(); // [?, ?]
var referenceToNFE = function testNFE() {
alert([
arguments.callee === referenceToNFE,
arguments.callee === testNFE
]);
}(); // [?, ?]
;-)
> And in the next one?
>
^^^^^^^^^^
> referenceToNFE(); // [?, ?]
> testNFE(); // [?, ?]
>
> var referenceToNFE = function testNFE() { [next example]
>
Sorry, two calls are related to the first one example. So should be:
[...]
referenceToNFE(); // [?, ?]
testNFE(); // [?, ?]
--------------------
And in the next one? [next example]
You can always distinguish them by checking `arguments.length` value of
course.
>
> var getClass = Object.prototype.toString;
>
> alert(getClass.call()); // [object Object]
Strange. I actually get "[object builtins]" here as well (Chrome 4.x on
Mac). Which version are you on?
> alert(getClass.call(undefined)); // [object builtins]
> alert(getClass.call(null)); // [object builtins]
Well this just makes their implementation non-conformant. We can file a
bug with Chromium. It looks like "builtins" is the [[Class]] of
`undefined` and `null`, or more likely [[Class]] of their internal
wrappers or something (that somehow get past `call`/`apply`'s primitive
coercion).
> alert(getClass.call(this)); // [object global]
>
> First three calls should use the global object as [thisArg] (by
> 15.3.4.4, ES-3), and the fours one - is real global object passed (in
> code of the global context), but as we can see Chrome treats this
> cases differently.
Yep. However, `toString` from <Global object>'s [[Prototype]] actually
returns "[object DOMWindow]". Apparently this next object in Global
Object's prototype chain is `DOMWindow.prototype` (where DOMWindow
doesn't seem to be exposed publicly).
(function(){ return this.__proto__.constructor; })();
/* function DOMWindow() { [native code] } */
So the proto chain there is apparently something like:
<Global Object> --> DOMWindow.prototype --> <...> --> Object.prototype
--
kangax
> [...]
> > Yeah, but e.g. Google Chrome seems to distinguish real [undefined]
> > value and [not passed] parameter:
>
> You can always distinguish them by checking `arguments.length` value of
> course.
>
Ah, that's just theoretical interest for me, no more; sure it's Chorme
implementations bug of call/apply methods.
>
>
> > var getClass = Object.prototype.toString;
>
> > alert(getClass.call()); // [object Object]
>
> Strange. I actually get "[object builtins]" here as well (Chrome 4.x on
> Mac). Which version are you on?
>
I have Chrome v.3.0.195.27 (WinXP). Yep, there were some changes in
4.x version, e.g. they removed JS-code implementation of native
methods from .toString:
In v.4.x you'll get standard:
alert([].push);
Result: function push() {[native code]}
And in 3.x sort of:
alert([].push);
function push() {
var n = ToUint32(this.length);
var m = _ArgumentsLength();
for (var i = 0; i < m; i++) {
this[i+n] = _Arguments(i);
}
this.length = n + m;
return this.length;
}
> > alert(getClass.call(undefined)); // [object builtins]
> > alert(getClass.call(null)); // [object builtins]
>
> Well this just makes their implementation non-conformant.
Yes, it's.
> It looks like "builtins" is the [[Class]] of
> `undefined` and `null`, or more likely [[Class]] of their internal
> wrappers or something (that somehow get past `call`/`apply`'s primitive
> coercion).
>
Yeah, kind of, on implementation level they have special namespace for
that Builtins::(...) where that entities are described.
> [...]
> Yep. However, `toString` from <Global object>'s [[Prototype]] actually
> returns "[object DOMWindow]". Apparently this next object in Global
> Object's prototype chain is `DOMWindow.prototype` (where DOMWindow
> doesn't seem to be exposed publicly).
>
> (function(){ return this.__proto__.constructor; })();
>
> /* function DOMWindow() { [native code] } */
>
> So the proto chain there is apparently something like:
>
> <Global Object> --> DOMWindow.prototype --> <...> --> Object.prototype
>
Yes, seems so, but e.g. FF also has "additional" objects in prototype
chain of the global object (not global -> Object.prototype directly):
alert(this.__proto__); // [xpconnect wrapped native prototype]
alert(this.__proto__.__proto__); // [object Global Scope Polluter]
alert(this.__proto__.__proto__.__proto__); // [object Object] -
Object.prototype appears only now
alert(this.__proto__.__proto__.__proto__.__proto__); // null, end of
the chain - Object.prototype.[[Prototype]]
/ds
NFE bug matters here only in a sense that there's an extra function
object created during variable declaration. This doesn't affect
resulting outcome of course, as variable that first reference this
function object is being reassigned value `1` shortly after (as Richard
mentioned).
But I know that you already know all of it :)
Original question is nice, but not as interesting as if it was changed
only slightly to something that would produce different results in
JScript and other environments:
var a,
b = function a(x) {
x && a(--x);
};
alert(a);
� and would require a knowledge of not only NFE as specified, but also
JScript bug and the order + semantics of function declarations /
variable declarations.
[...]
--
kangax