Are you a javascript expert? Test

1864 views
Skip to first unread message

optimistx

unread,
Oct 26, 2009, 6:31:27 AM10/26/09
to
What does the alert statement in these 5 cases output, exactly?Of course,
the test should be done without debugger, without executing,without googling
, with honesty ...1)if (!("a" in window)) {
var a = 1;
}
alert(a);2)var a = 1,
b = function a(x) {
x && a(--x);
};
alert(a);3)
function a(x) {
return x * 2;
}
var a;
alert(a);4)
function b(x, y, a) {
arguments[2] = 10;
alert(a);
}
b(1, 2, 3);5)
function a() {
alert(this);
}
a.call(null);The code was copied (without doublechecking)
fromhttp://dmitry.baranovskiy.com/

rf

unread,
Oct 26, 2009, 7:08:01 AM10/26/09
to

"optimistx" <opti...@hotmail.com> wrote in message
news:4ae57a79$0$26343$9b53...@news.fv.fi...
> What
bloody atrocious layout.


Richard Cornford

unread,
Oct 26, 2009, 7:18:33 AM10/26/09
to
On Oct 26, 10:31 am, optimistxwrote:

> What does the alert statement in these 5 cases output, exactly?
> Of course, the test should be done without debugger, without
> executing,without googling , with honesty ...

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.

Garrett Smith

unread,
Oct 26, 2009, 1:26:44 PM10/26/09
to
Richard Cornford wrote:
> On Oct 26, 10:31 am, optimistxwrote:

[...]


>> 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/

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 2:10:18 PM10/26/09
to
On Oct 26, 2:18 pm, Richard Cornford <Rich...@litotes.demon.co.uk>
wrote:

> [...]


> 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

Jorge

unread,
Oct 26, 2009, 2:48:51 PM10/26/09
to
On Oct 26, 11:31 am, "optimistx" <optimi...@hotmail.com> wrote:
> What does the alert statement in these 5 cases output, exactly ?
> Of course,
> the test should be done without debugger, without executing,
> without googling, with honesty ...

function f () { return 1; }

if (true) {
function f () { return 2; }
} else {
function f () { return 3; }
}

alert(f()); // ?
--
Jorge.

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 2:59:10 PM10/26/09
to
On Oct 26, 9:48 pm, Jorge <jo...@jorgechamorro.com> wrote:

> 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

Jorge

unread,
Oct 26, 2009, 3:16:23 PM10/26/09
to
On Oct 26, 7:59 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:
>
> By the spec, btw, this cases are *not correct* at all. (...)

I know :-) What does IE do ?
--
Jorge.

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 3:26:32 PM10/26/09
to
On Oct 26, 10:16 pm, Jorge <jo...@jorgechamorro.com> wrote:

>
> [...]


>
> I know :-) What does IE do ?
>

IE does [3] as treats this function as FD.

Jorge

unread,
Oct 26, 2009, 4:54:31 PM10/26/09
to
On Oct 26, 8:26 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:

> On Oct 26, 10:16 pm, Jorge <jo...@jorgechamorro.com> wrote:
>
> > I know :-) What does IE do ?
>
> IE does [3] as treats this function as FD.

As it does with FEs too :-)
--
Jorge.

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 6:15:51 PM10/26/09
to
On Oct 26, 11:54 pm, Jorge <jo...@jorgechamorro.com> wrote:

>[...]


> As it does with FEs too :-)

> [...]
>

Only for named FEs ;)

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 6:29:46 PM10/26/09
to
Back to IE (and it's implementation of NFE): what will alert show in
example above?

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
]);

}(); // [?, ?]

;-)

Dmitry A. Soshnikov

unread,
Oct 26, 2009, 6:37:30 PM10/26/09
to
On 27 окт, 01:29, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:

> 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]

kangax

unread,
Oct 27, 2009, 12:42:08 AM10/27/09
to
Dmitry A. Soshnikov wrote:
> On Oct 26, 2:18 pm, Richard Cornford <Rich...@litotes.demon.co.uk>
> wrote:
>
>> [...]
>> 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:

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

Dmitry A. Soshnikov

unread,
Oct 27, 2009, 5:04:45 AM10/27/09
to
On Oct 27, 7:42 am, kangax <kan...@gmail.com> wrote:
> Dmitry A. Soshnikov wrote:

> [...]


> > 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

kangax

unread,
Oct 27, 2009, 12:34:05 PM10/27/09
to
Dmitry A. Soshnikov wrote:
> On Oct 26, 2:18 pm, Richard Cornford <Rich...@litotes.demon.co.uk>
> wrote:
>
>> [...]
>> 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.

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

Reply all
Reply to author
Forward
0 new messages