Dynamic loading of javascript files into web pages

J

Jorge

Mention that *you* consider it harmful.

Plus a link to the convoluted non-arguments(*) in your (OMG) long
post...

(*)
1.- WTHIT ?
javascript:alert(document.createElement
("script").canHaveHTML):undefined

2.- Wow:
"The file name changed it's not "menu.js", but now "menu-
degrading.js",
but notice how Steve gets that wrong a couple of times. That right
there
is evidence that the "degrading" part is unrelated to the original
code."

3.- That says nothing about the validity of the pattern:
"The inline code at the end of menu-degrading.js loops through
elements
in the document. It uses all global variables, including a global
loop
counter |i|."

4.- The same global context in which any program (read: <script>) is
run:
"The eval method is called in global context."

5.- idiocy++ ?:
"Looping through the DOM while the page loads is a strategy that
hurts
performance."

6.- Again ?
"AISB, eval is called in global context. Steve did not mention this,
and
the code is so naive that I doubt he is even aware of it"

7.- Of course, it's a <script>, remember ?
"but the code must exist in global context"

8.- Etc...
 
G

Garrett Smith

Any rational person reading that couldn't really disagree that what I
wrote was incorrect based on the fact that it was long. The review was
not nearly as long as the video itself

The video contains so much maladvice that a complete review would be
longer than the video itself.

The arguments were valid, clearly stated, and addressed one of the
video's topics in overview and specifics. Steve's advice on application
design and architecture is dangerous and should be eschewed.
Plus a link to the convoluted non-arguments(*) in your (OMG) long
post...

It was long, I should have trimmed it up a bit. But it was not nearly as
long as the video, right?

That video is potentially harmful. Someone might watch that and
actually believe it was useful.
(*)
1.- WTHIT ?

I take it that means "what the hell is this". It is an MSIE property.
I should have mentioned that |canHaveHTML| is an MSIE property[5].

(BTW - the MSDN doc came up #1 in google rank for "canHaveHTML".)
javascript:alert(document.createElement
("script").canHaveHTML):undefined


2.- Wow:
"The file name changed it's not "menu.js", but now "menu-
degrading.js",
but notice how Steve gets that wrong a couple of times. That right
there
is evidence that the "degrading" part is unrelated to the original
code."

The confusion it causes should not be surprising; rather, it is
indicative that the technique is confusing.
3.- That says nothing about the validity of the pattern:
"The inline code at the end of menu-degrading.js loops through
elements
in the document. It uses all global variables, including a global
loop
counter |i|."

Steve says the technique is "safer". It is less safe because of the use
of eval. That point should have been clear. It is also unsafe because,
AISB, it is based on the expectation that all browsers violate HTML 4.01
to make it work.

Garrett
[5]http://msdn.microsoft.com/en-us/library/ms533547(VS.85).aspx
 
J

Jorge

Garrett said:
Jorge wrote:
(...)
1.- WTHIT ?

I take it that means "what the hell is this". It is an MSIE property.
I should have mentioned that |canHaveHTML| is an MSIE property[5].
(...)
AISB, it is based on the expectation that all browsers violate HTML 4.01
to make it work.
(...)

True, <script>s can (and should) not contain *markup* and nobody is
asking for it. In the absence of (inner) markup, .innerHTML becomes ===
..innerText === .textContent === .text. If it makes you feel any better
use the latter. Although -I can only guess- they must have chosen
..innerHTML for a reason.

see:
http://jorgechamorro.com/cljs/070/
 
J

Jorge

(...)
Steve says the technique is "safer". It is less safe because of the use
of eval. That point should have been clear.(...)

BTW, could you explain to me why/how is it any unsafer eval
(script.text) than a <script> tag ?

TIA,
 
G

Garrett Smith

Jorge said:
Garrett said:
Jorge wrote:
(...)
1.- WTHIT ?

I take it that means "what the hell is this". It is an MSIE property.
I should have mentioned that |canHaveHTML| is an MSIE property[5].
(...)
AISB, it is based on the expectation that all browsers violate HTML
4.01 to make it work.
(...)

True, <script>s can (and should) not contain *markup* and nobody is
asking for it. In the absence of (inner) markup, .innerHTML becomes ===
.innerText === .textContent === .text. If it makes you feel any better
use the latter. Although -I can only guess- they must have chosen
.innerHTML for a reason.

Script content is CDATA[1]. That means it must *not* contain markup.
While that is true, it is not the incompliance that I mention.

What I am talking about is the HTML 4.01 requires the browser to ignore
the element's contents when the script has a URI. See HTML 4.01, 18.2.1
The SCRIPT element:

| If the src attribute is not set, user agents must interpret the
| contents of the element as the script. If the src has a URI value,
| user agents must ignore the element's contents and retrieve the script
| via the URI.

"*must* *ignore*"

And 6.14 Script data:

| User agents must not evaluate script data as HTML markup but instead
| must pass it on as data to a script engine.

And section 6.2 SGML basic types:
| ...
| Although the STYLE and SCRIPT elements use CDATA for their data model,
| for these elements, CDATA must be handled differently by user agents.
| Markup and entities must be treated as raw text and passed to the
| application as is.

Now, in a browser that does not support the script element, it should,
(or must, in other specifications) attempt to process the element's
content.

HTML 4.01, B.1 Notes on invalid documents:
| # If a user agent encounters an element it does not recognize, it
| should try to render the element's content.

XHTML 1, 3.2. User Agent Conformance:
| # If a user agent encounters an element it does not recognize, it must
| process the element's content.

The choice of judgment to use |script.innerHTML| is based on the
expectation that the script will have an innerHTML property containing
the script data as text, that gets passed as-is to eval. That
expectation is, according to Steve Souders, based upon what "all
browsers" do.

Garrett
 
G

Garrett Smith

Jorge said:
BTW, could you explain to me why/how is it any unsafer eval
(script.text) than a <script> tag ?

The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.

When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.

Using a SCRIPT tag, that behavior does not happen.

Garrett
 
J

Jorge

BTW, could you explain to me why/how is it any unsafer eval
(script.text) than a <script> tag ?

The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.

When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.

Using a SCRIPT tag, that behavior does not happen.

Thanks, but AFAICS, an eval('code') at the top level is ===
<script>'code'</script> :

- 'this' === window,
- [[scope]] === global context, and
- no Variable 'object'.
 
J

Jorge

The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.
When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.

I know that ES3 allows for implementations to throw EvalError with
indirect eval calls, but don't browsers instead evaluate in a global scope?

(this happens in at least FF 3 and Safari 4)

var x = 'outer';
(function(){
   var x = 'inner';
   return this.eval('x');

})();

var x = 'outer';
(function f () {
var x = 'inner';
alert(window.eval('x'));
})();

--> outer

var x = 'outer';
(function f () {
var x = 'inner';
alert(eval('x'));
})();

--> inner
 
D

David Mark

The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.
When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.

I know that ES3 allows for implementations to throw EvalError with
indirect eval calls, but don't browsers instead evaluate in a global scope?

Some might if the Global Object is used. Don't count on it though
(better strategy is to count on an exception.)
(this happens in at least FF 3 and Safari 4)

I wouldn't infer anything from that.
var x = 'outer';

AIUI, this would be more future-proof with regard to the next version
of ES:

var GLOBAL = this;
(function(){
   var x = 'inner';
   return this.eval('x');

return GLOBAL.eval('x');

But best to avoid it entirely.
 
D

David Mark

The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.
When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.
Using a SCRIPT tag, that behavior does not happen.

Thanks, but AFAICS, an eval('code') at the top level is ===
<script>'code'</script> :

- 'this' === window,

Bad assumption, but irrelevant here.
- [[scope]] === global context, and

Not exactly.

And are you planning to run this XHR/eval combo in the global
context? I would expect it to reside in a function.
- no Variable 'object'.

See above.
 
D

David Mark

Garrett said:
Jorge wrote:
(...)
Steve says the technique is "safer". It is less safe because of theuse
of eval. That point should have been clear.(...)
BTW, could you explain to me why/how is it any unsafer eval
(script.text) than a <script> tag ?
The eval function uses the calling context's [[Scope]], Variable object,
and |this| value.
When eval is called, and the code inside eval is parsed, assignment to
identifiers inside that eval'd code resolve to the calling context's
variable object when it is invoked.
I know that ES3 allows for implementations to throw EvalError with
indirect eval calls, but don't browsers instead evaluate in a global scope?
(this happens in at least FF 3 and Safari 4)
var x = 'outer';
(function(){
   var x = 'inner';
   return this.eval('x');

var x = 'outer';
(function f () {
   var x = 'inner';
   alert(window.eval('x'));

There's no guarantee that this method will exist on the window object,
which is not necessarily the Global Object anyway.
})();

--> outer

var x = 'outer';
(function f () {
   var x = 'inner';
   alert(eval('x'));

})();

--> inner

Proves absolutely nothing.
 
D

David Mark

I don't think that's necessary. The only person who frequently asked
this question is Jorge, and he won't need an FAQ entry about it. He's
promoting some links/videos which he considers valuable, and I don't
think he'll stop until he receives a plausible explanation.

Jorge, I see what you're doing, and I understand the motivation, but
adding the same list of links after every repost of FAQ 3.2 isn't going
help much. I suggest you make a separate post about these links, and ask
why they shouldn't be included in the FAQ. Maybe we'll get some kind of
review out of that thread. Personally, I've become a bit disillusioned
by Douglas Crockford's idea of the "Good Parts" of JavaScript. This is
mostly due to what I've seen on the JSLint mailing list.




Thanks for transcribing the video, but usually bloopers are ommitted
from a transcription. Reproducing them verbatim ("menu jay") doesn't
really serve any purpose, unless you want to discredit the speaker.
Giving a presentation without making mistakes is a LOT harder that
writing a piece of text.


JFTR, I don't recommend this technique either. The fact that it's
invalid HTML is reason enough for me. AFAIK, neither Souders nor Resig
actually use it anywhere. As far as I'm concerned, it's just an
experiment, and shouldn't be given so much attention, and Souders
shouldn't present it as a viable way to improve preformance. He has
other, much better solutions for loading scripts asynchronously.


What's so bad about a calling a separate function to do the eval()? This
will make sure that the JS string is always evaluated in global context,
and it also keeps the 'eval' out of the loader code, which makes
minification easier:

function evil (code) {
    return eval(code);

}

// later...
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        // ....
        evil(xhr.responseText);


This is why we use settings/flags for these optimizations: turn them off
during development and bugfixing, turn them on in production (assuming
that the optimization won't create any bugs by itself). Some library
(Dojo?) automatically adds a comment line at the end of script files to
help in debugging, and I recently read a blog post where somebody
suggested that these hints should be standardised (for debuggers like
FireBug). Can't find the link right now, might have been on Ajaxian.

Similar hints could be added to the example above:

function evil (code, url) {
    if (url) {
        code += "\n// source: " + url;
    }
    return eval(code);

}

// later...
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        // assuming scriptURL was set earlier:
        evil(xhr.responseText, scriptURL);


It may be more complex, and less clear, but performance tweaks often
are. There's always a tradeoff. I don't think his example code is usable
as-is, but his overview of techniques and the analysis of current
browser behaviors is interesting. Two slides at the end of the
presentation ("impact on revenue" and "cost savings") indicate that for
some companies, at least, the added complexity may well be worth it.


But at least it's valid, and it should be well enough supported, as long
as XHR is available. I'm actually using this technique in a small
project since April (about 80 users, not in a LAN environment), just to
see if there are any practical problems with this approach. If there
were, the XHR injection could be turned off by flipping a config
setting, but so far it hasn't been necessary.


I thought he said there was no single "best" solution. Anyway, the
expandos shouldn't hurt if you choose their names carefully, and you
could easily implement the same thing without expandos if you think they
are that dangerous.


If the FAQ had a more comprehensive book list, okay. But as long as that
isn't the case, why single out this book as "bad advice", and ignore all
the other books which couldn't be included in the FAQ because they
contain errors?

No way his book is going in the FAQ, unless it is specifically
recommended against.

This is another one of these guys who think programming is making
videos of themselves, using the word "awesome" a lot, congratulating
fellow ignoramuses on their videos, etc. He very obviously knows
nothing about browser scripting or sound Web development techniques
(echoing the familiar Web2.0 follies of the last four years or so.)
These hucksters are part of the past; never mind if their programs are
still in syndication (so is Gilligan's Island.)
 
O

One Dumm Hikk

The problem is:

- Given a script that has not been loaded yet (still loading), -
usually a dynamically inserted one-,
- Find the best way to have some piece of code run asap, immediatly
after the script (above) has loaded and executed.

(note that "onload" is not -usually- available on <script> tags in
most browsers)

That is trivial to do. Again, people try to make this stuff
harder than it has to be. Want a fool proof way to make a script
in an external file execute and know that is has loaded? Search
the archives, I have shown this MANY times and it was even before
many people knew JRs name.
At the end of the external file, place the call to the function
that you want executed. It will NOT get executed until the file
is loaded and it will get called only when the file gets loaded.
Stop making this harder than it has to be. Sheesh people.

I'm not sure why do you say so, as it's obvious (isn't it ?) that
latency times add up when the scripts are loaded in series.

I say that because its patently true. Unless you want to try to
convince me that connection speed is determined by how the file
was attempted to be loaded. Again, take a HARD look at the original
script, how it was written, and how it would work. Then let's
discuss what it will or won't do.
And for servers that throttle downloads (more and more each day, e.g.
youtube, me.com...), the time to download n scripts in parallel is not
necessarily === n* the time to download a single one.

How a file is called is irrelevant to the amount of time it takes to
download that file. IE is notorious for loading multiple files at once
irregardless of how you try to load it.

For a file that is of size S, it will take a given amount of time T,
to
download the file from the server *irregardless of how its requested*
if
all other parameters are equal. Same network speed, same processes on
the
computer making the request, same server load.

The difference it makes is the appearance of loading faster by
rendering
the HTML aspects of the page first.

Has John Resig gotten any clue about JS in the last 18 months or so?
If he hasn't, then he still doesn't have a clue.
 
J

Jorge

Once again, you show the experiment but not the reasoning that gets you
from the results of that experiment to your (very general) conclusion.

There is also some significant information missing, such as how many
simultaneous HTTP connections the server delivering the JS files is
configured to allow. Because while the HTTP spec states that only 2
simultaneous connections should be made to a server (RFC 2616, Section
8.1.4, Paragraph 6) some user agents have been observed to make
considerably more (10 to 20 in extreams).

In this regard the limiting factor seems to be in the browsers
themselves not in me.com.
The problem with deducing your general conclusion that "Parallel script
loading SEVERELY cuts scripts loading time" from your experiment is that
your experiment takes place after the page has loaded; at a time when
parsing and (progressive) rendering are not active and when there is no
ongoing demand to be downloading resources (when no HTTP connections are
being called upon to do other things).

Yes, and ... ? Of course when/if there aren't for any reason any more
available download "slots" downloading can't/won't take place in
parallel.
All that actually is shown by the experiment is that if you only use one
HTTP connection (download resources serially) the process takes longer
than if you use more than one connection at the same time. Hardly
surprising as if the number of connections made did not influence
download performance then there would be no reason for ever making more
than one connection to a server at a time.

Yes and no. The point is that a series of <script> tags hardcoded in
the source .html will be loaded in series while the same <scripts>
inserted dynamically load in parallel.

And then the problem of synchronizing load times and execution times
arises, hence Resig's degrading script tag idea becomes relevant as a
solution to a problem previously inexistent.

See: http://jorgechamorro.com/cljs/071/

It times the loading of 4 scripts:

(1)- dynamically inserting them all at once
(2)- dynamically inserting them in series
(3)- document.writting them all at once
(4)- normally: 4 <script> tags hardcoded in the .html source.

(1) is the fastest in all the current and past browsers. Only the
latest Safari 4, FF3.5 beta and Opera 10 beta manage to speedup (3)
and sometimes (4) as well.

All the action now takes place before onload.
 
J

Jorge

One said:
That is trivial to do. Again, people try to make this stuff
harder than it has to be. Want a fool proof way to make a script
in an external file execute and know that is has loaded? Search
the archives, I have shown this MANY times and it was even before
many people knew JRs name.
At the end of the external file, place the call to the function
that you want executed.

Yes we do that in e.g. every JSONP response.
It will NOT get executed until the file
is loaded and it will get called only when the file gets loaded.
Stop making this harder than it has to be. Sheesh people.



I say that because its patently true. Unless you want to try to
convince me that connection speed is determined by how the file
was attempted to be loaded. Again, take a HARD look at the original
script, how it was written, and how it would work. Then let's
discuss what it will or won't do.

<script>s hardcoded in the source .html halt parsing and download in
series, while dynamically inserted ones don't halt parsing and download
in parallel.
How a file is called is irrelevant to the amount of time it takes to
download that file.

It isn't, see above.
IE is notorious for loading multiple files at once
irregardless of how you try to load it.

For a file that is of size S, it will take a given amount of time T,
to
download the file from the server *irregardless of how its requested*
if
all other parameters are equal. Same network speed, same processes on
the
computer making the request, same server load.

We're talking about parallel download therefore we're talking of
several, more than one files.
The difference it makes is the appearance of loading faster by
rendering
the HTML aspects of the page first.

Has John Resig gotten any clue about JS in the last 18 months or so?
If he hasn't, then he still doesn't have a clue.

DM in disguise ?
 
D

David Mark

Yes we do that in e.g. every JSONP response.

Good for you.
 > It will NOT get executed until the file


That f() must be a global and requires a previous, separate <script>.
Resig's solution requires none of these.

Resig has no solutions, only snake oil. You are the only one in here
stupid enough to miss that.
<script>s hardcoded in the source .html halt parsing and download in
series, while dynamically inserted ones don't halt parsing and download
in parallel.

Re-read the thread from the beginning.
It isn't, see above.

Or just read what you quote.
We're talking about parallel download therefore we're talking of
several, more than one files.

Randy knows what he is talking about. You haven't got the slightest
clue.
DM in disguise ?

See what I mean?
 
J

Jorge

Conrad said:
I don't think that's necessary. The only person who frequently asked
this question is Jorge, and he won't need an FAQ entry about it. He's
promoting some links/videos which he considers valuable, and I don't
think he'll stop until he receives a plausible explanation.

Jorge, I see what you're doing, and I understand the motivation, but
adding the same list of links after every repost of FAQ 3.2 isn't going
help much. I suggest you make a separate post about these links, and ask
why they shouldn't be included in the FAQ. Maybe we'll get some kind of
review out of that thread.

They've got "their" own FAQ, I've got my own posts... :)
Personally, I've become a bit disillusioned
by Douglas Crockford's idea of the "Good Parts" of JavaScript. This is
mostly due to what I've seen on the JSLint mailing list.

Why ?
Thanks for transcribing the video, but usually bloopers are ommitted
from a transcription. Reproducing them verbatim ("menu jay") doesn't
really serve any purpose, unless you want to discredit the speaker.
Giving a presentation without making mistakes is a LOT harder that
writing a piece of text.


JFTR, I don't recommend this technique either. The fact that it's
invalid HTML

Is it ? Sure ? it's got text content not markup... (?)
 
O

One Dumm Hikk

Yes we do that in e.g. every JSONP response.

 > It will NOT get executed until the file


That f() must be a global and requires a previous, separate <script>.
Resig's solution requires none of these.

Pure nonsense. It doesn't have to be global nor does it
"require a previous, seperate <script>".
f() can be a property of a single global object and the call
can be made in the same file that you are loading. I know that
to be true because its the way I have been doing it for many
years now. Download a .js file that has data in it with a
function call at the end of the file that deals with the
data in the file. That is how you deal with the issue of
knowing when/if the file is downloaded or not. It is
the ONLY *reliable* way to know that the data file has
downloaded.

Perhaps you should search the c.l.j archives for
"dynamic script insertion" and spend the next two
weeks or so reading the many many threads on this
topic.
<script>s hardcoded in the source .html halt parsing and download in
series, while dynamically inserted ones don't halt parsing and download
in parallel.

And that is precisely what I said. It doesn't change the download time
it
takes, it changes the rendering time to render an initial page so that
you fool the uneducated into thinking the page has finished "loading"
because they see content. Witness mySpace and its abominable use of
AJAX to try to "speed up" the site when in fact its a classic example
of the *wrong way* to speed up a site.
DM in disguise ?

That question, in and of itself, displays your level of knowledge
of what you are attempting to discuss. Try searching the archives
for the suggested search, read it all, and then get back to me.
Because as it stands now, your question shows that you have made
no effort to research the archives to find out about the subject
you are trying to portray yourself as an expert on.

I am not what I would consider an "expert" on the topic but I simply
have done a TON of research in the last 10 years or so on the topic
and a perusal of the archives would answer many of the questions you
are trying to - incorrectly - answer.
 
J

Jorge

Pure nonsense. It doesn't have to be global nor does it
"require a previous, seperate <script>".
f() can be a property of a single global object and the call
can be made in the same file that you are loading. I know that
to be true because its the way I have been doing it for many
years now. Download a .js file that has data in it with a
function call at the end of the file that deals with the
data in the file.

Yes, the properties you attach to a global object are global too.
And yes, f() must have been declared somewhere (in a previous,
separate said:
That is how you deal with the issue of
knowing when/if the file is downloaded or not. It is
the ONLY *reliable* way to know that the data file has
downloaded.

Perhaps you should search the c.l.j archives for
"dynamic script insertion" and spend the next two
weeks or so reading the many many threads on this
topic.

You mean, that perhaps, I'd find there something else that's not being
said here ?
A secret or something ?
And that is precisely what I said. It doesn't change the download time
it
takes, it changes the rendering time to render an initial page so that
you fool the uneducated into thinking the page has finished "loading"
because they see content.

Now it looks like you're focusing on the "doesn't halt parsing" aspect
while conveniently forgetting about the "and download in parallel
(read: faster)" side of things.
Witness mySpace and its abominable use of
AJAX to try to "speed up" the site when in fact its a classic example
of the *wrong way* to speed up a site.



That question, in and of itself, displays your level of knowledge
of what you are attempting to discuss. Try searching the archives
for the suggested search, read it all, and then get back to me.
Because as it stands now, your question shows that you have made
no effort to research the archives to find out about the subject
you are trying to portray yourself as an expert on.

How's posting code that proves what I say is pretending ?
 
T

Thomas 'PointedEars' Lahn

Conrad said:
What's so bad about a calling a separate function to do the eval()? This
will make sure that the JS string is always evaluated in global context,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You are mistaken, as proven recently. Find the proof below again, in a more
elaborated form.
and it also keeps the 'eval' out of the loader code, which makes
minification easier:

function evil (code) {
return eval(code);

Now include variable declarations in `code'. Not only that the variables
will not be available globally afterwards, as I have showed; they will also
be deletable (as per Specification), as Martin has pointed out.

function isMethod(o, p)
{
if (/^\s*(undefined|unknown)\s*$/i.test(typeof o)) return false;

var t = typeof o[p];
return (/^\s*unknown\s*$/i.test(t)
|| /^\s*(function|object)\s*$/i.test(t) && o[p]);
}

function dmsg(s, bShow)
{
if (typeof console != "undefined"
&& isMethod(console, "log"))
{
console.log(s);
}
else if (bShow
&& typeof window != "undefined"
&& isMethod(window, "alert"))
{
window.alert(s);
}
}

function evil(code)
{
var result = eval(code);

/* 1. typeof x === "number" */
dmsg('1. typeof x === "' + typeof x + '"', true);

/* 2. typeof y === "number" */
dmsg('2. typeof y === "' + typeof y + '"', true);

delete x;

/* 3. typeof x === "undefined" */
dmsg('3. typeof x === "' + typeof x + '"', true);

/* 4. typeof y === "number" */
dmsg('4. typeof y === "' + typeof y + '"', true);

return result;
}

/* 5. evil(...) === 42 */
dmsg('5. evil(...) === ' + evil("var x = 1, y = 2; 42"), true);

/* 6. typeof y === "undefined" */
dmsg('6. typeof y === "' + typeof y + '"', true);


PointedEars
 

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

Forum statistics

Threads
474,098
Messages
2,570,625
Members
47,236
Latest member
EverestNero

Latest Threads

Top