JavaScript knowledge test

D

dhtmlkitchen

[Trimmed quote, seehttp://www.jibbering.com/faq/faq_notes/clj_posts.htmlandhttp://netmeister.org/news/learn2quote.html]



[...] (e-mail address removed) wrote:
new Boolean( false ); will produce the same result in
IE and in FF, I think this is a bug.
It is not a bug. The specification requires - new Object(false) - to be
the exact equivalent of - new Boolean(false) - and - new
Object("false") - to be the exact equivalent of - new String("false") -.
So if your "b is a ... ; not a String or string literal" where taken as
referring to String objects and string primitives then - new
Object("false") - would not be allowed anyway (the resulting value is a
String object).
Ah, that would explain why:
typeof new Object( "foo" );//Object
new Object( "foo" ).constructor // String
What a funny language.

The author of JavaScript himself is not quite happy with the type
distinction between primitive types like boolean and string, and object
types like Boolean and String:

http://weblogs.mozillazine.org/roadmap/archives/2005/11/js2.html
That's a lot to take in.

It appears that unboxing has been implemented in ES4.

Here's a console printout from ES4:

So it's new behavior, but I think it's a good thing; the current
behavior in es3 is misleading to developers.

Garrett
 
R

Richard Cornford

No need for the pity! I just didn't read that post yet. ...
<snip>

You have quoted the significant section of my post twice now in your own
posts. Not reading the material you quote is a reckless way of behaving
on Usenet.

Cool! So that is the answer,

Not the answer to the question you actually asked. Rather the (but
possibly on an) answer to the question that you thought you had asked.
and it does fulfill the 'built-in' req.
Sorry for leading you all astray with the Object
constructor.

And the use of - typeof - in the actual question.
That was actually what I thought at first (Boolean object),
but then when I read the steps for evaluating an 'if'
statement, I saw that it called GetValue. I'm not
understanding how GetValue works;

Section 8.7, and then section 8.6.2 for the [[Get]] method of objects.

The GetValue function turns instances of the internal Reference type
into the value of the property named by the "property name" of the
Reference type on the object referred to by the "base" of Reference
type. Whenever the argument to GetValue is not a Reference type the
argument itself is returned (unaltered).

Identifier resolution against the scope chain and the evaluation of
property accessors result in Reference type. The only other expression
that may result in a Reference type is a grouping operation, where the
parentheses of the grouping operator surrounding an Identifier or a
property accessor (only) (or a call to a host function/method, but there
is no evidence that any implementations have taken advantage of that
provision).
does it try to take the
object as a variable from the containing scope?

The wording of that question is too far detached form anything that has
meaning in javascript to be answered.
I don't get it. Someone esplain, please.

I've debugged code like this. At a prominent company in
Sunnyvale,

As I recall VK claims to work (or have worked) in Sunnyvale. There must
be quite a trail of buggy and irrational code following him about.
I found code that used the Boolean constructor in a conditional.

It was the use of - Boolean.prototype - that I observed that I had never
seen in practice. The Boolean constructor is often used (called as a
function) to do type-conversion to boolean.
It was
as if they wanted if(!!maybeUndefined),

That would be redundant as the type-conversion to boolean is implied in
the evaluation of the - if - expression (step 3 in both of the
algorithms of Section 12.5). You could just write - if(
maybeUndefined ){ ... } - as if the Identifier is undeclared in addition
to its value possibly being undefined then all these permutations would
error out anyway.
but instead used if( new Boolean( maybeUndefined ) ).
But definitely not a common case, you're right.

I can see how that might happen (assuming VK was not responsible as that
is the type of thing he would do anyway).

Bollean( x)

- is guaranteed to have the same result as:-

!!x

- and is proposed to be superior (if slower) because it is
self-documenting (that is, states at the point of forcing the
type-conversation what type is expected to be the outcome). But if you
expose - Boolean(x) - to JSLint it will flag the failure to use the -
new - operator with the Boolean constructor (Douglas prefers !!x for
type conversion). So correcting that without thinking about what was
happening might turn a reasonable, but redundant, - if( Boolean( x )){
.... } - into a faulty - if( new Boolean( x )){ ... } -.
I learned a lot about debugging others' code there. The Boolean
thing was just one small anomaly. Fortunately, they were pretty
patient with me and didn't take my code fixes too personally.

I've seen 'with' but only for simple examples, and not in any
recent code.

In my opinion there is only one valid use for - with - (explicit scope
chain augmentation of function expressions), but the situations where
that is either necessary or even advantageous are so few and far between
that I would not expect to see it used more than once in maybe 50,000
lines of code (assuming knowledgeable authors of that code).
Ah, that would explain why:
typeof new Object( "foo" );//Object
new Object( "foo" ).constructor // String

Yes it would.
What a funny language.

But sharing with all programming languages the characteristics of being
completely logical and predictable, and so understandable.

Richard.
 
R

Richard Cornford

Richard Cornford wrote:
"Inspired" by one of the more ambiguous questions on your
meebo.com page I thought the following might make quite
interesting written test questions, and give an impression
of my thought process in setting javascript questions:-

/* unknown global code */
function outerFunction(){
/* unknown outer function body code */
function innerFunction(){
/* unknown inner function body code */
with(anObjectReference){
x = 5; //<--- The subject line of code.
}
/* more unknown inner function body code */
}
/* more unknown outer function body code */
}
/* more unknown global code */

/* ********************************************************\
| Note: Three facts about the 'unknown' code:- |
| |
| 1. There are no more function definitions, no function |
| expressions and no uses of the Function constructor. |
| 2. There are no - with - statements in the unknown code.|
| 3. There are no uses of the - eval - function. |
\******************************************************** */

Q1: Assuming the line that reads - x = 5; - is executed, which
(group of) of the following are possible outcomes of its execution?

[My second question, quoted out of sequence:-]
| Q2: If the line of code above is changed from - x = 5; - to -
| var x = 5 - which (group of) the above are then the possible
| outcomes of the execution of that line?

At the point where the line of code is executed the - with - statement
has augmented the scope chain by adding an object to the top (or front,
depending on how you want to look at it) of it. Giving a scope chain
consisting of 4 objects; the object added with the - with - statement,
the Activation/Variable object from the execution context in which the -
x = 5; - line is executing, the Activation/Variable object associated
with the outer function when the inner function object was created, and
finally the global object.

The unknowns in this code allow any object to be the one added at the
top of the scope chain, and for any local variables to have been
declared in any function or globally, and so result in either
Activation/Variable object and the global object having any properties
when the - x = 5; - line is executed.

The procedure for resolving Identifiers such as - x - is to start at the
top of the scope chain and examine the object there to see if it has a
property with a name that corresponds with the Identifier. The nature of
this examination is to call the object's internal [[HasPropery]] method,
which, in the even that it cannot find a property on the object itself,
calls the [[HasProperty]] method of the object that is referred to by
its [[Prototype]] (if it is not null). Thus the test to see if the
object has a property with the given name is applied to the object and
all the objects on its prototype chain.

If the first object on the prototype chain does not have a property with
the corresponding name the testing moves to the next object in the
chain, and the test is repeated on that object, and so on until either
an object with a property with the corresponding name is found or the
scope chain comes to an end and there are no more objects to examine.

If an object on the scope chain (or one of its prototypes) is found to
have a property with the corresponding name the result of the resolution
of the Identifier is a Reference type with its 'base' property set to a
reference to the object on the scope chain, and its 'propertyName'
property set to the name of the property found (that is, the
Identifier).

If no object on the scope chain (or any of their prototypes) was found
to have a property with the corresponding name the result is again a
Reference type with its 'propertyName' property set to name that
corresponds with the Identifier, but this time the 'base' property is
set to null.

An assignment involves evaluating the expression to be assigned (to the
numeric value 5 in our case) and then resolving the left hand side of
the assignment into a Reference type (or generating a runtime error if
that is not possible) and then assigning the value of the right hand
expression to a property of the object referred to by 'base' property of
the Reference type with the name that is the Reference type's
'propertyName' value. If the Reference type's 'base' property is null
the global object becomes the substitute and it receives the assigned
value in one of its properties. And whenever the object (itself, not its
prototypes) does not already have a property with the corresponding name
one is created on it.

Thus the type of outcomes that are possible with - x = 5; - and - var x
= 5; - are the assignment of the value 5 to properties of objects and a
possible side effect of creating new properties of (some of) those
objects as a consequence. The subjects of the individual answers are
then which of these actions could possibly be applied to the various
objects that are of interest here, in the context of the code (both
specified and possible).

A quick listing of my answers, where 'P' indicates a 'Possible' and 'N'
a 'Not Possible':-

| x = 5 | var x = 5
----|---------|-----------
1 | P | P
2 | P | P
3 | P | P
4 | P | P
5 | P | P
6 | P | P
7 | N | N
8 | P | N <<- Changed by adding - var -.
9 | N | N
10 | P | P
11 | N | N
12 | P | P
13 | P | P
14 | P | P
15 | P | P
16 | P | P
17 | P | P
--------------------------

Some answers can be regarded as, as RobG suggested, splitting hairs, and
others may seem that way. However, with the exception of items such as
#7, where getting it wrong would be fatal, coming up with an answer that
differs from mine is neither unacceptable nor unexpected. My interest is
more in how the individuals react to being shown why they were wrong.

#1, #3 and #5 being examples of this. The question hangs on the
interpretation of the exact wording (the subject is always the object
itself not its prototypes) so it is very easy to miss the distinction
between the object as you would interact with it in code (where it
behaves as if it has all the properties of its prototype) and the object
as it really is. If someone says that the answers are 'not possible'
because they perceive that and object inheriting a property from a
prototype is equivalent to its having that property then that is a
viable and acceptable way of looking at the situation. My interest would
be in seeing whether, being shown how #1 is possible, they perceived the
implications for #3 and #5 immediately (and #13 and #15 in the - var x
= 5; - case, but more on that later).

(Though all credit to those who do spot the possibility, and so -
zeroglif@gmai ... - who posted the demonstration of the possibility
within a minute of my posting that there was a proof of the possibility,
and so independently of my post implying that looking for a proof might
be worth the effort).

So to the answers:-
1. The creation of an 'x' property of the 'outerFunction'
function and the assignment of the value 5 to that property.

x = 5; - As has been discussed, 'outerFunction' is a discrete object
that inherits properties from its prototypes (Function.prototype and
Object.prototype). If the - with - statement is used to put a reference
to it at the top of the scope chain the testing of that object to see if
it 'has' an 'x' property, using its internal [[HasProperty]] method,
will return true if the property is defined on either prototype but not
the object itself. Then the assignment would target the 'outerFunction'
object and create a property on that object as a side effect:-

Object.prototype.x = 0;

function outerFunction() {
function innerFunction() {
var anObjectReference = outerFunction;
alert(outerFunction.hasOwnProperty('x')); //false
with (anObjectReference) {
x = 7;
}
alert(outerFunction.hasOwnProperty('x'));//true
}
innerFunction();
}
outerFunction();

The - hasOwnProperty - method being a good indicator of whether the
object itself has the property in question.

#1 is possible.

var x = 5; - The situation is not altered by declaring a function local
variable for 'innerFunction' because the Variable object for
'innerFunction' is below whatever object the - with - statement added to
the scope chain and so when that added object becomes the target for the
assignment the scope chain resolution of the 'x' Identifier stops and so
never gets to innerFunctios' Variable object. #1 is possible.
2. The assignment of the value 5 to a pre-existing 'x' property
of the 'outerFunction' function.

x = 5; - If 'outerFunction' has an 'x' property and it is placed at the
top of the sc0pe chain by the - with - statement the assignment is going
to target that property of that object. #2 is possible.

var x = 5; - Again the situation is not altered by declaring a function
local variable for 'innerFunction'. #2 is possible.
3. The creation of an 'x' property of the 'innerFunction'
function and the assignment of the value 5 to that property.

x = 5; - 'innerFunction' and its prototypes can be subject to exactly
the same manipulations as 'outerFunction' and it can also be placed at
the top of the scope chain. #3 is possible.

var x = 5; - The situation is not altered by declaring a function local
variable for 'innerFunction'. #3 is possible.
4. The assignment of the value 5 to a pre-existing 'x' property
of the 'innerFunction' function.

x = 5; - Whatever is possible for 'outerFunction' is possible for
'innerFunction'. #4 is possible.

var x = 5; - The situation is not altered by declaring a function local
variable for 'innerFunction'. #4 is possible.
5. The creation of an 'x' property of the object referred to by
'anObjectReference' and the assignment of the value 5 to that
property.

x = 5; - if something is possible for 'outerFunction' as a result of
making it "the object referred to by 'anObjectReference'" it must also
be possible for the object referred to by 'anObjectReference'. #5 is
possible.

var x = 5; - The situation is not altered by declaring a function local
variable for 'innerFunction'. #5 is possible.
6. The assignment of the value 5 to a pre-existing 'x'
property of the object referred to by 'anObjectReference'.

x = 5; Same as #5. #6 is possible.

var x = 5; - The situation is not altered by declaring a function local
variable for 'innerFunction'. #6 is possible.
7. The creation of a local variable of the 'outerFunction'
function named 'x' and the assignment of the value 5 to
that variable.

x = 5; An assignment does not declare a variable. #7 is not possible
(getting this one wrong is fatal).

var x = 5; - Declaring a function local variable for 'innerFunction' is
not declaring a function local variable for 'outerFunction' (and that is
assuming that "the execution of that line" could result in "the
creation of a local variable" at all). #7 is not possible (getting this
one wrong is fatal).
8. The assignment of the value 5 to a declared local variable
of the 'outerFunction' function named 'x'.

x = 5; Yes, if 'outerFunction' included a declaration of a local
variable 'x' and no object higher on the scope chain had an 'x' property
then the assignment of the value 5 to that local variable is the
expected outcome. #8 is possible (getting this one wrong is fatal).

var x = 5; - Declaring a function local variable for 'innerFunction'
results in its Variable object having an 'x' property, and its variable
object is above that of 'outerFunction' on the scope chain so the
Identifier resolution can never get to the Variable object for
'outerFunction'. (it is not possible to reference any Variable object
except the global object, so the - with - statement cannot be used to
put the 'outerFunction' Variable object at the top of the scope chain.)
#8 is not possible (getting this one wrong is fatial).
9. The creation of a local variable of the 'innerFunction'
function named 'x' and the assignment of the value 5 to
that variable.

x = 5; An assignment does not declare a variable. #9 is not possible
(getting this one wrong is fatal).

var x = 5; - Strictly this is not possible because the questions ask
about the "outcomes of the execution of that line" and the local
variable that results for the variable declaration here was created
during variable instantiation for the execution context. That is, the
variable already exists at that time of the execution of the line, and
so cannot be created at that time.

The existence of the line - var x = 5; - does result in "The creation of
a local variable of the 'innerFunction' function named 'x'" and may
result in "the assignment of the value 5 to that variable" but the
_execution_ of the line does not. #9 is not possible.
10. The assignment of the value 5 to a declared local variable
of the 'innerFunction' function named 'x'.

x = 5; This is entirely possible. #10 is possible (getting this one
wrong is fatal).

var x = 5; - This is entirely possible, and you don't need any other
variable declarations for 'x' (even though they are allowed (not
encouraged)) because, as I mentioned for #9, the variable declaration
here has created a local variable during variable instantiation, and so
at the time of executing the line a local variable of the
'innerFunction' is certain to be in existence. #10 is possible (getting
this one wrong is fatal).
11. The creation of a global variable named 'x' and the
assignment of the value 5 to that variable.

x = 5; Here is the hair-splitting quibble; The declaration of a
variable results in the creation of a property of an object (a Variable
object) and the declaration of a global variable results in the creation
of a property of the global object (because the global object is used as
the Variable object for variable instantiation in the global execution
context). And if no object on the scope chain is found to have an 'x'
property then the result of the assignment is the creation of an 'x'
property of the global object, which certainly is also a consequence of
declaring a global variable.

However, there are two reasons for not considering the runtime creation
of a property of the global object as being "the creation of a global
variable". The first, and most arguable, is timing; variables are
created during variable instantiation and prior to the execution of any
code for the execution context in question. The second is that
properties of objects created during variable instantiation in function
and global execution contexts are marked with the - DontDelete -
attribute. Thus a global variable cannot be deleted with the - delete -
operator, a runtime-created property of the global object can be deleted
so it is not a global variable. #11 is not possible. (Quibbling about
variable instantiation in - eval - code execution contexts remains a
possibility. And a candidate taking that line would act to impress
(possibly just for their knowing the specifics of the eval case)).

var x = 5; - Not possible, but remember that it is possible to put the
global object at the top of the scope chain, and if you can get at the
prototype for the global object (if it has one at all) then the
technique used in #1 can be applied to create a property of the global
object with the execution of this line of code. So it is a good thing
that creating a property of the global object alone could not be
considered as "the creation of a global variable". #11 is not possible.
12. The assignment of the value 5 to a declared global
variable named 'x'.

x = 5; - #12 is possible (getting this wrong is fatal).

var x = 5; If the global object is the one placed at the top of the
scope chain by the - with - statement, and it has a global variable
named 'x' then the execution of this line of code will assign the value
5 to that global variable. #12 is possible.
13. The creation of an 'x' property of the global object and the
assignment of the value 5 to that property.

x = 5; - #13 is possible (getting this wrong is fatal).

var x = 5; ECMA 262 3rd Ed. is unspecific on the subject of the
prototype of the global object. It allows that the global object may
have no prototype at all, but leaves it to the implementation to decide
how to handle the situation. Now suppose the global object inherits
from - Object.prototype -, which is hardly an unexpected thing for an
object in javascript to do, then the technique used in #1 can be applied
here to create a property of the global object at runtime. #13 is
possible.
14. The assignment of the value 5 to a pre-existing 'x' property
of the global object.

x = 5; - #14 is possible (getting this wrong is fatal).

var x = 5; If the global object is the one placed at the top of the
scope chain by the - with - statement, and it has an 'x' property then
the execution of this line of code will assign the value 5 to that 'x'
property of the global object. #14 is possible.
15. The creation of an 'x' property of the window object and
the assignment of the value 5 to that property.

x = 5; - There is no requirement that there be a window object at all,
and in WSH and ASP, for example, there is no window object (the concept
has no meaning in host contexts), but in a web browser environment the
window object is expected to be the same object as the global object
(and expectation that can be observed as being rewarded in actual
browsers). There is nothing in the questions that preclude the code from
being executed in a web browser where the ECMAScript global object is
the window object, and so #15 is possible.

var x = 5; - if the window object and the global object are the same
object then whatever can be done with the global object can also be done
with the window object, so as #13 is possible #15 is possible.
16. The assignment of the value 5 to a pre-existing 'x' property
of the window object.

x = 5; - If the window object and the global object are the same object
then whatever can be done with the global object can also be done with
the window object, so as #14 is possible #16 is possible.

var x = 5; - If the window object and the global object are the same
object then whatever can be done with the global object can also be done
with the window object, so as #14 is possible #16 is possible.
17. A runtime error.
<snip>

x = 5; - Disregarding possible sources of errors on the preceding line
(or in other places in the code) which may prevent the subject line of
code being executed (and so are precluded by the presupposition that it
is executed implied by the question), it has been demonstrated that this
line can be made to error in environments as common as IE 6. #17 is
possible.

var x = 5; - If, in IE 6, you create the conditions that have been
described to make - x = 5; - error, and then place the window/global
object at the top of the scope chain with the - with - statement, then
you get the same error with - var x = 5; -. #17 is possible.

------------------------------------------------------

Given the number of seriously counter-intuitive possibilities introduced
by the use of the - with -, particularly things like - var x = 5; -
occurring nested two functions deep can still set the value of a global
variable, I hope that leaves nobody in any doubt as to why the use of
the - with - statement is _strongly_ discouraged in production
javascript. But still, if you have applied for a job as a javascript
expert is there an excuse for not knowing what the - with - statement
does, or not understand code that does use it?

It should also be seen that the strict observance of many other 'best
practice' notions would impact on these questions. Such as 'if you are
using something that is conceptually a global variable it should always
be explicitly declared as a global variable'. Which precludes the stated
IE 6 runtime errors, any questions of playing around with the prototype
of the global object and any hair splitting about whether a property of
the global object is a variable or not. And the suggestion that
function local variables should all be explicitly declared at the start
of a function body (so in a context that mirrors the order of their
handling, i.e. declarations being handled during variable instantiation,
prior to the actual execution of any function body code) guarantees that
they cannot then appear inside a Block Statement, and so cannot appear
where they may be (or appear to be) influenced by a scope chain
augmented by the - with - statement.

Then again, there were also counter-intuitive possibilities introduced
by prototype inheritance, which is pretty fundamental to what javascript
is.

Going back to my inspiration for the question, the meebo.com page's
question:-

| 2. What's the difference between these two statements:
|
| a. var x = 3;
|
| b. x = 3;

- (Remembering that the only answer to the questions above that changed
as a result of using - var - was the answer to #8.) does anyone still
think it can be answered at all? Or answered concisely but not
trivially? Or that the person setting that question would see any
accurate answer given as an indication of the expertise they were
looking for?

Richard.
 
R

Richard Cornford

Zeroglif said:
Thanks Richard, that was really interesting.
Any plans for new test?

No plans, and certainly not in the short term. You have to remember that
I have a practical use for these questions and posting that question
denies me the possibility of using it myself.

On the other hand I liked RobG's suggestion in response to #17 that a
question could be directed at runtime errors. You could start off with a
set of conditions such as:-

1. The environment is a (hypothetical) scriptable HTML web
browser.
2. The script implementation is 100% ECMA 262 3rd Ed. conforming.
3. The ECMAScript global object has a - window - property that
is a reference to the ECMAScript global object.
4. The ECMAScript global object has a - document - property that
is a reference to an object.
5. There are no uses of the - with - statement, the - eval -
function or the - Function - constructor anywhere on the page.
6. The code shown never appears in HTML attribute values (unless
explicitly stated).

- and probably some others that I have not yet thought of. (it might be
worth saying that the object referred to by - document - implements ECMA
262 conforming [[Get]] and [[Put]] methods, and maybe that chunks of
pre-DOM are implemented; location, history, frames, forms, links,
anchors, etc.)

Ask the question "Which of the following can never result in a runtime
error?", and provide a list of blocks of code (possibly, and
particularly in the case of function definitions, including details of
how the code is used/called).

And so see how easily people perceive the boundary between what is
'safe' and what is not (and some other things such as putting line that
obviously may error inside and - if - were the condition can never be
true, and so see if they observe that there cannot be an error because
the error producing line cannot be executed).

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top