new Function(...) abuse in FAQ?

N

Nickolay Ponomarev

Hi,

Why does http://www.jibbering.com/faq/ uses new Function constructor
instead of function expressions (function(...) { ... }) when defining
new functions? E.g. for LTrim and toFixed. Is the reason that you want
to avoid accidental closures? Or does some obscure browser does not
support function expressions?

This just looks weird, given that http://www.jibbering.com/faq/#FAQ4_40
says to only use eval() (which is not really much different from new
Function()) only for evaluating code that only becomes known at
run-time.

Nickolay
 
N

Nickolay Ponomarev

Peter said:
Nice, but I don't see an explanation why it has to be the way it is
currently in that thread.

As to what's wrong with new Function(),
a) it gives a bad example
b) the code is supplied as a string, which leads to
b-1) syntax highlighters not working on it => harder to read, easier
to miss an error
b-2) the need for extra escapes (took me several seconds to see that
\\s in regexp in the trim implementation was not an error.

Nickolay
 
R

Richard Cornford

Nickolay said:
Hi,

Why does http://www.jibbering.com/faq/ uses new Function
constructor instead of function expressions (function(...) { ... })
when defining new functions?

Mostly because much of it was written half a decade ago when anything else
would not have been cross-browser. It has remained because it a. it still
works fine, b. no compelling argument has ever been presented for changing
it (leaving it largely a matter of taste as to whether it gets changed).
E.g. for LTrim and toFixed. Is the reason that
you want to avoid accidental closures?

Avoiding needlessly forming closures is a reason for using the function
constructor to create functions, though those specific examples would form
problematic closures.
Or does some obscure browser does not
support function expressions?

What a strange question. No pre-ECMA 262 3rd edition implementations can be
expected to support inner functions, and some certainly did not.
Fortunately, with the standard having remained stable for so long we have
just arrived (over the last two or three years) at the point where current
browsers are all, more or less, bug free ECMA 262 3rd edition
implementations. Probably, Konqueror 2 was the most recent browser that did
not understand nested functions. Konqueror 3.x is currently pretty close to
being ECMA 262 3rd Ed.
This just looks weird, given that
http://www.jibbering.com/faq/#FAQ4_40 says to only use eval()
(which is not really much different from new Function()) only
for evaluating code that only becomes known at run-time.

While all (at least almost all) of the abuses of - eval - can be reproduced
using the Function constructor is does not then follow that uses of the
function constructor are then all equivalent to - eval - abuses. Indeed, it
is difficult to see how the use of the - Function - constructor to construct
function objects could qualify as an abuse of it.

Richard.
 
R

Richard Cornford

Nickolay Ponomarev wrote:
Nice, but I don't see an explanation why it has to be the
way it is currently in that thread.

As to what's wrong with new Function(),
a) it gives a bad example

You should not expect anyone to give much credence to an argument that says
"it gives a bad example" is you do not state what it is that it gives an
example of, or what it is that is bad about it.

Remember that the world of web development is plagued with uninformed
opinions, hearsay, lies, poor advice, rumours and mystical incantations. We
even have browser's like Mozilla/Gecko spitting out spurious and bogus
"warnings" (along side very reasonable warnings, but to the detriment of
their general credibility) if you are fool enough to turn that facility on.

If there is a reason for a particular course of action that reason can be
stated in full and so judged on its own merits. In this very thread that is
already at least one statement that is factually false, but still being put
forward as a reason for a particular course of action. We would not want to
take your "it gives a bad example" seriously and then discover that it was
motivated by a similar misconception.
b) the code is supplied as a string, which leads to
b-1) syntax highlighters not working on it => harder to
read, easier to miss an error

True, but that only leads to the position that creating complex functions
with the Function constructor is probably not a good idea. Where a function
body consists of only a single statement it is unlikely that either of
syntax highlighting or error locating are going to be significant issues. A
reasonable cut-off might be proposed at, say, 4 statements.
b-2) the need for extra escapes (took me several seconds
to see that \\s in regexp in the trim implementation was not
an error.

But for most functions constructed in that way no escaping is necessary at
all. And with regular expressions you have similar escaping issues when
using the RegExp constructor to process a string into a regular expression
object (would that imply never using that constructor?).

Generally I am not in favour of people even attempting to script the
creation of scripts (which is what constructing function bodies as strings
and then turning those into function objects with the Function constructor
is), but I am also not in favour on knee-jerk reactions to particular (and
potentially, even if rarely) useful constructs. An ability to make informed
decisions about what is done is far more useful.

Richard.
 
R

Richard Cornford

David said:
http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/f40e66
f39de1fd27/d3f306c325bb00af?lnk=gst&q=petermichaux+faq+function+constructor&
rnum=1#d3f306c325bb00af>

c) it is inefficient (performance-wise) for the same reason
that "eval" is inefficient - the code is re-parsed each time
it's used, instead of only once, as normal functions are

Not true. Once a function object has been constructed the method of
construction no longer has any influence on its performance. And while
generating a function object from a string at runtime can be slow in some
environments such a method of function object creation has been demonstrated
to be (at least some of the time) the fasted available in others (IE 6).
d) it discourages beginning JS programmers from learning
about properly dealing with closures and memory leak issues

Beginner javascript programmers are not going to easily understand closures
whatever you do. However, if they create faction objects with the
constructor they will not be creating closures so they will not need to
clean them up. Though it could easily be argued that there can be no such
thing as "properly dealing with closures and memory leak issues" because if
things were being done "properly" (by the browser makers) there would be no
memory leak issues.
e) it doesn't have the advantage of lexical scoping,
which is an important feature in JavaScript functions
(when properly used)

Lexical scoping is not "an advantage", it is a reality. Its existence in the
language introduces the possibility to apply designed control over the scope
chains of functions, but there is only one way of creating a function with
the shortest possible scope chain from within another function, and that is
by using the Function constructor. Full control over the scope chains of
functions requires an ability to fully control the scope chains of function
objects, including the ability to create a function with the minimum scope
chain.
f) it encourages bad program design

It facilitates designed control over an important aspect of function
objects.
and inefficient code,

Is that assertion a result of you false belief that the functions is
re-parsed each time it is executed?
as decisions that should be made before writing can be put off
until run-time (as string concatenations, for example)
<snip>

A decision that can be made at the design stage should not be put off until
run-time, but not all decisions can be made at that point.
 
N

Nickolay Ponomarev

You should not expect anyone to give much credence to an argument that says
"it gives a bad example" is you do not state what it is that it gives an
example of, or what it is that is bad about it.
I said what's bad about it right below. The reason I started with (a)
is that this is what I'm mainly concerned about. I would expect clj FAQ
to give good examples.
We even have browser's like Mozilla/Gecko spitting out spurious and bogus
"warnings"

Any examples? (I know this is off-topic, but since I'm a bit familiar
with moz and never heard of these, you got me interested)
Mostly because much of it was written half a decade ago when anything else
would not have been cross-browser. It has remained because it a. it still
works fine, b. no compelling argument has ever been presented for changing
it (leaving it largely a matter of taste as to whether it gets changed).

You could save me and yourself some time by only posting this. You
answered my question. Thanks

Nickolay
 
R

Richard Cornford

Nickolay said:
I said what's bad about it right below.

So that was that strings are not internally syntax highlighted and that
it might be difficult to spot code errors in such strings. Both of
which are largely mitigated if the contents of function body strings
used with the Function constructor are limited in their internal
complexity. Certainly not enough to justify labelling their use as
giving "a bad example".
The reason I started with (a)

"it gives a bad example" is hardly a reason, as it does not state what
that bad example is, or what it bad about it.
is that this is what I'm mainly concerned
about. I would expect clj FAQ to give good examples.

It is not necessarily possible to regard any simple example as good or
bad. You have concerned yourself with the explicit declaration of
variables (in a nearby thread), but what is to stop someone seeing an
example of such and making a bad application of a declaration such as
features in the second example of code in what follows?
Any examples? (I know this is off-topic, but since I'm a bit familiar
with moz and never heard of these, you got me interested)

Given the code:-

if(window.clipboardData){
alert('clipboard')
}

Mozilla 1.6 (for no other reason than it is the Mozilla version on this
machine) outputs the warning:-

"Warning: reference to undefined property window.clipboardData"

- while with:-

if((typeof window.clipboardData) == 'object'){
alert('maybe clipboard, or null')
}

- it does not. In the case of the first code the property accessor -
window.clipboardData - is evaluated into a Reference type, a value
retrieved using that Reference type and that value type-converted to
boolean. In the second case the property accessor -
window.clipboardData - is evaluated into a Reference type, a value
retrieved using that Reference type and then the type of the value used
to determine one of a set of string values, which is then compared with
a string literal to produce a boolean result.

If any point in those processes can be ladled as a "reference to
undefined property" that should occur in the process of using the
Reference type to retrieve a value (as the creation of the Reference
type has no interest in whether any object assigned to its 'base'
property has a property with the name used as its 'propertyName'
property). Both of the examples above use the same Reference type to
retrieve the same value, so if one produces a warning and the other
does not then either the warning it spurious when it is produced in
the first case or its absence is bogus in the second.

Given the code:-

function testFunc(param){
var param; // This is a "bad" application of the otherwise "good"
// declaration of local variables.
}

Mozilla outputs the warning:-

"Warning: variable param hides argument"

- and that is an absolute lie. ECMA 262 is very clear about how such
code should be handled (Section 10.1.3) and not only does the - var
param; - not "hide" the - param - formal parameter it is actually
specified as doing nothing (that is, the local variable declaration
does not replace the pre-existing property of the Variable object with
the name - param -, and it does not modify its value). It would be
possible for the warning to express the pointlessness of declaring a
local variable with the same name as a function's formal parameter, but
outputting a factually false statement instead is wrong, and
undermines the credibility of all the warnings generated on the system.

Are you re-ordering the material you are quoting (without stating as
much)? That would generally be regarded as disingenuous.
You could save me and yourself some time by only posting this. You
answered my question.
<snip>

I was interested in whether you would present any compelling arguments
for changing the FAQ. You have not.

Richard.
 
R

Randy Webb

Richard Cornford said the following on 1/23/2007 6:05 AM:
Nickolay Ponomarev wrote:

<snip>

I was interested in whether you would present any compelling arguments
for changing the FAQ. You have not.

<G> You have noticed a lack of change in the code in the FAQ, no? <G>
 
N

Nickolay Ponomarev

Richard said:
It is not necessarily possible to regard any simple example as good or
bad. You have concerned yourself with the explicit declaration of
variables (in a nearby thread), but what is to stop someone seeing an
example of such and making a bad application of a declaration such as
features in the second example of code in what follows?
Right. As you noticed, I think that using Function constructor should
be avoided, unless using it has benefits. This is why I called the
examples in the FAQ "bad". Apparently, you and others who have a say
over what is in the FAQ disagree. Oh well.
Given the code:-

if(window.clipboardData){
alert('clipboard')
}

Mozilla 1.6 (for no other reason than it is the Mozilla version on this
machine) outputs the warning:-

"Warning: reference to undefined property window.clipboardData"
It seems this no longer happens in newer versions. (1.6 is three years
old.)
Given the code:-

function testFunc(param){
var param; // This is a "bad" application of the otherwise "good"
// declaration of local variables.
}

Mozilla outputs the warning:-

"Warning: variable param hides argument"

- and that is an absolute lie. ECMA 262 is very clear about how such
code should be handled (Section 10.1.3) and not only does the - var
param; - not "hide" the - param - formal parameter it is actually
specified as doing nothing

Right, that's how it works, and the warning is indeed a bit misleading.
Thanks for mentioning it.
Are you re-ordering the material you are quoting (without stating as
much)? That would generally be regarded as disingenuous.
Am I? Sorry if I did. I do have the habit of snipping large portions of
text, but usually don't reorder it.
<snip>

I was interested in whether you would present any compelling arguments
for changing the FAQ. You have not.
There are no compelling arguments for changing it if you don't think
that putting code in string literals for no reason is wrong. I hoped
somebody would tell me the reason for *not* changing it. Apparently
people here just like the Function constructor more.

(You probably noticed, as did guy who called me a jerk in the other
thread, that I got off on the wrong foot the day I first replied. Sorry
if I offended you, you're a nice and helpful fellow. Thanks for your
replies.)

Nickolay
 
R

Randy Webb

Nickolay Ponomarev said the following on 1/23/2007 2:55 PM:
Right. As you noticed, I think that using Function constructor should
be avoided, unless using it has benefits. This is why I called the
examples in the FAQ "bad". Apparently, you and others who have a say
over what is in the FAQ disagree. Oh well.

For a very long time a lot of people complained about what was in the
FAQ but never proposed an alternative. If you have alternative code that
accomplishes the same goal without drawbacks then post it. If it doesn't
get whammied to death then it can be changed in the FAQ. But to simply
say "I think that's wrong/bad" without offering an alternative is a
quick route to it not getting changed. But, if it comes down to Richard
saying "The code is fine" then I will give you 100-1 that it will stay
the way it is. If you post alternative code and Richard doesn't disagree
with it then you get another 100-1 that it will get changed.

Right, that's how it works, and the warning is indeed a bit misleading.

I wouldn't call an "absolute lie" a "bit misleading". It is 100% totally
misleading and blatantly wrong.

There are no compelling arguments for changing it if you don't think
that putting code in string literals for no reason is wrong. I hoped
somebody would tell me the reason for *not* changing it. Apparently
people here just like the Function constructor more.

He explained why it was written the way it was written. If browsers are
to the point where they can handle a different construct then fine.
(You probably noticed, as did guy who called me a jerk in the other
thread, that I got off on the wrong foot the day I first replied. Sorry
if I offended you, you're a nice and helpful fellow. Thanks for your
replies.)

Nothing in Usenet is worth getting offended over. By tomorrow, there
will be another 40 or so posts to move on to. But, as for being a jerk,
welcome to the jerk club, I have been called a lot worse than that :)
 
N

Nickolay Ponomarev

Nickolay Ponomarev said the following on 1/23/2007 2:55 PM:


FAQ but never proposed an alternative. If you have alternative code that
accomplishes the same goal without drawbacks then post it. If it doesn't
get whammied to death then it can be changed in the FAQ. But to simply
say "I think that's wrong/bad" without offering an alternative is a
quick route to it not getting changed. But, if it comes down to Richard
saying "The code is fine" then I will give you 100-1 that it will stay
the way it is. If you post alternative code and Richard doesn't disagree
with it then you get another 100-1 that it will get changed.
I thought the alternative was obvious, so I didn't mention it. If it
wasn't obvious, here it is:
String.prototype.LTrim = function(s) { return this.replace(/^\s+/,'');
}

The browsers/JS engines I care about can handle this, but I'm sure
somebody will come up with a reason this is totally wrong and shouldn't
be in the FAQ. I don't care too much though, and It's not very
important.
<snip>




misleading and blatantly wrong.
The point of the warning is that you have a |var|-declared variable and
a parameter with the name, and it gets the point across.

BTW, this will be fixed for Firefox 3 and other Gecko 1.9-based apps,
thanks to Richard's notice.

Nickolay
 
R

Richard Cornford

Nickolay said:
Right. As you noticed, I think that using Function constructor
should be avoided, unless using it has benefits.

Which is a reasonable position, but not necessarily better justified
than a position that says that the use of the Function constructor
should only be avoided when its use does no harm. A distinction further
blurred by the realisation that the decision is not made on a single
axis, but instead in a space where many factors influence what may be
regarded as 'benefit' and 'harm', some of which are context related.
This is why I called the examples in the FAQ "bad".

We have seen the specifics: the maintenance headaches and debugging
problems that follow form indirect scripting. Both are valid and
realistic concerns, but more significant with an increase in the size and
complexity of the indirect scripting used. Thus the relative simplicity
of the examples in the FAQ may be argued to mitigate those concerns in
the specific case, and the "bad example" then follows from people seeing
how the Function constructor can be used and extending that to
realisation of what may be done with them, while perhaps not thinking of
undesirable consequences that follow from the elaboration of the example.

It is almost certainly true that if the example in the FAQ were created
today it would be written to assign the results of function expressions
instead of functions constructed with the constructor. However, the
result may still be validly subject to the accusation that it was a "bad
example" because an individual seeing such an example might also see how
the assigning of function expressions could be applied in other contexts
(such as assigned directly to event handlers) and so elaborate the
example into a script that leaked memory in IE browsers (possibly not
noticing at first and incorporating the technique to such an extent that
when the problem was exposed the effort needed to mitigate it had become
a real maintenance headache).
Apparently, you and others who have a say
over what is in the FAQ disagree. Oh well.

The FAQ doesn't really work like that. If there was a sufficient
expression of opinion (from those who's opinions are worth listening to
(so not VK for obvious reasons)) in favour of a change (or a really
compelling argument) then a change would likely follow. (for example, I
have never been in favour of including David Flanagan's book(s) in the
FAQ, yet I added the entry based upon the weight of opinion expressed in
the group.

To the best of my recollection Yep and Evertjan (among some less
significant others) have expresses the opinion that the FAQ should change
from using the Function constructor to using function expressions. You
have added your voice and it probably would not take many more expressing
a similar opinion to qualify as sufficient.

From my point of view it could still go either way, which is shy I am
interested in the possible existence of a compelling argument for one
position or the other. Though I would not like to see the FAQ deprived of
all examples of the use of the Function constructor (this it, I don't
think its use is inherently bad).
It seems this no longer happens in newer versions. (1.6 is three
years old.)

It is good to hear that someone has finally come to their senses and
removed that nonsense. It remains depressing to think of all of the
examples of needlessly convoluted code uses in place of simpler
alternatives in order to avoid those "warnings" by people who would (or
could) not see that the warning made no sense in ECMAScript terms and
instead preferred to think of the authors of Mozilla as all-knowing
authorities on the writing of browser scripts (an extremely questionable
position even if the "warning" had not now been rescinded).
Right, that's how it works, and the warning is indeed a bit
misleading.

"A bit misleading"?
Thanks for mentioning it.

I suppose I should have a go at tracking down the other couple of
spectacularly bad "warnings" that have been brought to my attention over
the years.

There are no compelling arguments for changing it if you don't
think that putting code in string literals for no reason is
wrong.

Doesn't that swing on "for no reason". We know that there was a reason
for putting the code in strings in the first place (that it was
originally done at a time when the alternative was non-viable for
cross-browser work). That reason is probably no longer relevant.
I hoped somebody would tell me the reason for *not*
changing it.

I don't think that there is still a reason for not changing it, on the
other hand, I have not seen a positive reason for changing it either.
Apparently
people here just like the Function constructor more.
<snip>

I don't think that is true. I don't think anyone should give in to an
assertion that the use of the Function constructor is always bad without
that being backed up with a pretty solid justification for that position
(something beyond the observation that its use can be objectively bad (on
many fronts) being extended into an absurd blanket injunction against its
use).

An ideal situation exists when individuals find themselves in a position
to assess the merits of any particular technique on an informed basis and
with a consideration of the context in which it may be applied. In such
circumstances there is no need for black and white injunctions, or
declarations of good and bad, as, where valid, those conclusions will
inevitably follow from understanding.

Richard.
 
N

Nickolay Ponomarev

I don't think that there is still a reason for not changing it, on the
other hand, I have not seen a positive reason for changing it either.
You are right. Perhaps both variants could be demonstrated.

Nickolay
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top