Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

When is a function not a function?

43 views
Skip to first unread message

David Mark

unread,
Sep 25, 2007, 10:09:58 PM9/25/07
to
I've got a collection of functions that accept a function or object
(paired with a method name) as a callback.

For the longest time I have relied on this test.

(typeof cb == 'function')

This should work as well, but I am not sure how well it degrades in
older browsers. I think there are issues with functions created in
another context (eg frame) as well.

(cb instanceof Function)

Then I came across this.

(!!fn && typeof fn != "string" && !fn.nodeName && fn.constructor !=
Array && /function/i.test( fn + "" ))

I'm sure it is wrong as it is from jQuery, but it makes me wonder if
there are bugs in older browsers that will mislead my test.

As an aside, I was looking at the jQuery source as some browser
sniffer I was arguing with on a blog cited it as part of an "everybody
is doing it" argument. I had glanced at it previously and dismissed
it based on its resemblance to Prototype. Upon closer inspection, it
makes Prototype look inspired. Suffice to say that anybody who
recommends it hasn't read the code. It's a horror show.

Peter Michaux

unread,
Sep 26, 2007, 12:43:48 AM9/26/07
to
On Sep 25, 7:09 pm, David Mark <dmark.cins...@gmail.com> wrote:
> I've got a collection of functions that accept a function or object
> (paired with a method name) as a callback.
>
> For the longest time I have relied on this test.
>
> (typeof cb == 'function')
>
> This should work as well, but I am not sure how well it degrades in
> older browsers. I think there are issues with functions created in
> another context (eg frame) as well.
>
> (cb instanceof Function)
>
> Then I came across this.
>
> (!!fn && typeof fn != "string" && !fn.nodeName && fn.constructor !=
> Array && /function/i.test( fn + "" ))
>
> I'm sure it is wrong as it is from jQuery, but it makes me wonder if
> there are bugs in older browsers that will mislead my test.

I don't like to assume incorrect because it is in jQuery. I am
surprised if they are testing in older browsers. The hip libraries
don't seem to do that.


> As an aside, I was looking at the jQuery source as some browser
> sniffer I was arguing with on a blog cited it as part of an "everybody
> is doing it" argument. I had glanced at it previously and dismissed
> it based on its resemblance to Prototype. Upon closer inspection, it
> makes Prototype look inspired. Suffice to say that anybody who
> recommends it hasn't read the code. It's a horror show.

In a talk at Google, John Resig, jQuery founder, said something like
"after fighting with browser bugs long enough an experienced
JavaScript program just uses navigator.userAgent." At least that is
how I understood his talk. He does say many really good things. You
can watch the video.

http://ejohn.org/blog/building-a-javascript-library/

I left a comment on that blog page about sniffing and he never did
really respond. Perhaps that future blog post to which he refers later
in the comments is still in the works. I'm interested to read it.

Tricky one: How do you feature test opacity support?

Peter

Richard Cornford

unread,
Sep 26, 2007, 4:29:25 AM9/26/07
to
David Mark wrote:
> I've got a collection of functions that accept a function
> or object (paired with a method name) as a callback.
>
> For the longest time I have relied on this test.
>
> (typeof cb == 'function')
>
> This should work as well, but I am not sure how well it
> degrades in older browsers.

The typeof operator is consistent when its subjects are not host
objects, and has been around since JavaScript 1.1, so well pre-dating
the 4th generation browsers.

> I think there are issues with functions created in
> another context (eg frame) as well.
>
> (cb instanceof Function)

Yes, the a Function constructor exists for each frame and each has
unique identity. That is also true of the Array constructor.

> Then I came across this.
>
> (!!fn && typeof fn != "string" && !fn.nodeName &&
> fn.constructor != Array && /function/i.test( fn + "" ))
>
> I'm sure it is wrong

That would depend on what you considered correct. It looks like the
subject of the test is expected to be any of a javascript function
(unwisely tested), a siring primitive, a DOM element and Array or a
value with falseness. Getting into a position where it is necessary to
make such a test betrays very poor code design.

There are no circumstances under which a function object would result
in - typeof fn != 'string' - being true or its having a - nodeName -
property or a constructor property that was a reference to the frame's
Array constructor (unless they had been explicitly added).

> as it is from jQuery, but it makes me wonder if
> there are bugs in older browsers that will mislead
> my test.

What makes you think that jQuery, or any of its like, was written with
any interest in, or knowledge of, 'older browsers'?

> As an aside, I was looking at the jQuery source as some
> browser sniffer I was arguing with on a blog cited it as
> part of an "everybody is doing it" argument.

If that was a valid argument we would not have seen the virtual
disappearance of people using - eval - to reference object properties
with constructed dot notation property accessors. There was a time when
"everybody" was doing that, but most have now learnt better.

> I had glanced at it previously and dismissed
> it based on its resemblance to Prototype. Upon closer
> inspection, it makes Prototype look inspired. Suffice
> to say that anybody who recommends it hasn't read the
> code. It's a horror show.

The code above speaks of poor design, but at least it is ECMA 262
conforming, so that is one up on Prototype.js.

Richard.

David Mark

unread,
Sep 26, 2007, 3:45:19 PM9/26/07
to
On Sep 26, 12:43 am, Peter Michaux <petermich...@gmail.com> wrote:
> On Sep 25, 7:09 pm, David Mark <dmark.cins...@gmail.com> wrote:
>
>
>
>
>
> > I've got a collection of functions that accept a function or object
> > (paired with a method name) as a callback.
>
> > For the longest time I have relied on this test.
>
> > (typeof cb == 'function')
>
> > This should work as well, but I am not sure how well it degrades in
> > older browsers. I think there are issues with functions created in
> > another context (eg frame) as well.
>
> > (cb instanceof Function)
>
> > Then I came across this.
>
> > (!!fn && typeof fn != "string" && !fn.nodeName && fn.constructor !=
> > Array && /function/i.test( fn + "" ))
>
> > I'm sure it is wrong as it is from jQuery, but it makes me wonder if
> > there are bugs in older browsers that will mislead my test.
>
> I don't like to assume incorrect because it is in jQuery. I am
> surprised if they are testing in older browsers. The hip libraries
> don't seem to do that.

Hip? I don't know how to apply that to a lump of JavaScript code. If
you are referring to Prototype, jQuery and the like, then crap would
be more appropriate.

>
> > As an aside, I was looking at the jQuery source as some browser
> > sniffer I was arguing with on a blog cited it as part of an "everybody
> > is doing it" argument. I had glanced at it previously and dismissed
> > it based on its resemblance to Prototype. Upon closer inspection, it
> > makes Prototype look inspired. Suffice to say that anybody who
> > recommends it hasn't read the code. It's a horror show.
>
> In a talk at Google, John Resig, jQuery founder, said something like

The blind leading the blind.

> "after fighting with browser bugs long enough an experienced
> JavaScript program just uses navigator.userAgent." At least that is

Or they realize that they are fighting their own poor designs.

> how I understood his talk. He does say many really good things. You
> can watch the video.

After reading his code and comments, I am completely uninterested in
anything he has to say on the subject of browser scripting.

>
> http://ejohn.org/blog/building-a-javascript-library/
>
> I left a comment on that blog page about sniffing and he never did
> really respond. Perhaps that future blog

He has responded with a lousy JavaScript library full of browser
sniffing, not to mention wide gaps in logic.

post to which he refers later
> in the comments is still in the works. I'm interested to read it.
>
> Tricky one: How do you feature test opacity support?
>

Put this in the head of your document. Then test for "setOpacity."

var global = this;
var setOpacity = (function() {
var i, l, html;
var doc = global.document;
var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];

if (doc) { html = (doc.getElementsByTagName)?
doc.getElementsByTagName('html'):doc.documentElement; }
if (html && html[0] && html[0].style) {
if (typeof html[0].style.filter != 'undefined') {
return function(el, o) {
var f;
if (el.filters) {
if (el.currentStyle && !el.currentStyle.hasLayout)
{ el.style.zoom = 1; }
f = el.filters.alpha;
if (typeof(f) != 'undefined') {
if (o == 1) {
f.enabled = false;
}
else {
f.enabled = true;
f.opacity = o * 100;
}
}
else {
if (el.style && typeof(el.style.filter) != 'undefined')
{ el.style.filter += "alpha(opacity=" + (o * 100) + ")"; }
}
}
}
}
i = 0;
l = opacityStyles.length;
while (i < l) {
if (typeof(html[0].style[opacityStyles[i]]) == 'string') {
return (function(s) { return function(el, o) { el.style[s] =
o; }; })(opacityStyles[i]);
}
i++;
}
}
})();

I just tested it in IE7, Opera 9, the latest Netscape and Mozilla
versions and the Windows Safari Beta. The original code it is based
on (from around 2003) has been tested on hundreds of agents.

Now how does the "hip" jQuery lib handle this? Browser sniffing of
course. Some people never learn.

David Mark

unread,
Sep 26, 2007, 4:02:51 PM9/26/07
to
On Sep 26, 4:29 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> David Mark wrote:
> > I've got a collection of functions that accept a function
> > or object (paired with a method name) as a callback.
>
> > For the longest time I have relied on this test.
>
> > (typeof cb == 'function')
>
> > This should work as well, but I am not sure how well it
> > degrades in older browsers.
>
> The typeof operator is consistent when its subjects are not host
> objects, and has been around since JavaScript 1.1, so well pre-dating
> the 4th generation browsers.
>
> > I think there are issues with functions created in
> > another context (eg frame) as well.
>
> > (cb instanceof Function)
>
> Yes, the a Function constructor exists for each frame and each has
> unique identity. That is also true of the Array constructor.
>
> > Then I came across this.
>
> > (!!fn && typeof fn != "string" && !fn.nodeName &&
> > fn.constructor != Array && /function/i.test( fn + "" ))
>
> > I'm sure it is wrong
>
> That would depend on what you considered correct. It looks like the
> subject of the test is expected to be any of a javascript function
> (unwisely tested), a siring primitive, a DOM element and Array or a
> value with falseness. Getting into a position where it is necessary to
> make such a test betrays very poor code design.

That's right. It is a very odd design. I just wondered about the
strange function-related testing.

>
> There are no circumstances under which a function object would result
> in - typeof fn != 'string' - being true or its having a - nodeName -
> property or a constructor property that was a reference to the frame's
> Array constructor (unless they had been explicitly added).

Makes sense to me.

>
> > as it is from jQuery, but it makes me wonder if
> > there are bugs in older browsers that will mislead
> > my test.
>
> What makes you think that jQuery, or any of its like, was written with
> any interest in, or knowledge of, 'older browsers'?

Good point. All of that userAgent string comparison nonsense is
apparently necessary to make their code work in a handful of newer
browsers.

>
> > As an aside, I was looking at the jQuery source as some
> > browser sniffer I was arguing with on a blog cited it as
> > part of an "everybody is doing it" argument.
>
> If that was a valid argument we would not have seen the virtual
> disappearance of people using - eval - to reference object properties
> with constructed dot notation property accessors. There was a time when
> "everybody" was doing that, but most have now learnt better.

I know it isn't a valid argument. The guy who posed it isn't a valid
programmer (or debater.) I won't mention any names, but he is
actually considered a JS expert by the uninformed and misled masses.
An unfortunate consequence of this is there are a lot of sites out
there using his bungled code.

>
> > I had glanced at it previously and dismissed
> > it based on its resemblance to Prototype. Upon closer
> > inspection, it makes Prototype look inspired. Suffice
> > to say that anybody who recommends it hasn't read the
> > code. It's a horror show.
>
> The code above speaks of poor design, but at least it is ECMA 262
> conforming, so that is one up on Prototype.js.

jQuery uses dollar sign variables, which I don't think are allowed
under the specification.

Peter Michaux

unread,
Sep 26, 2007, 5:22:28 PM9/26/07
to
On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:

> jQuery uses dollar sign variables, which I don't think are allowed
> under the specification.

Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
sign is intended for use only in mechanically generated code."

After reading all the uproar about dollar signs in variables or even
one character dollar sign variable, I think it would have been better
if they had left this statement of intention out of the spec. A dollar
sign can or cannot be in an identifier. If it can then it is up to the
programmer to decide how to use it. If I was writing JavaScript to
last 100 years and knew JavaScript would be backwards compatible with
the exception of new keywords, I would probably start all my
identifiers with a dollar sign (eg. $foo, $bar) to avoid clashes with
new keywords.

Peter

David Mark

unread,
Sep 26, 2007, 5:36:00 PM9/26/07
to
On Sep 26, 5:22 pm, Peter Michaux <petermich...@gmail.com> wrote:
> On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:
>
> > jQuery uses dollar sign variables, which I don't think are allowed
> > under the specification.
>
> Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
> sign is intended for use only in mechanically generated code."

I understand that, but I don't think the authors of these libraries
are robots.

>
> After reading all the uproar about dollar signs in variables or even
> one character dollar sign variable, I think it would have been better
> if they had left this statement of intention out of the spec. A dollar
> sign can or cannot be in an identifier. If it can then it is up to the
> programmer to decide how to use it. If I was writing JavaScript to
> last 100 years and knew JavaScript would be backwards compatible with
> the exception of new keywords, I would probably start all my
> identifiers with a dollar sign (eg. $foo, $bar) to avoid clashes with
> new keywords.

The biggest problem I have is naming functions "$" or "$$" or anything
like that. If you minify your production code then the only argument
for these is to reduce the total number of keystrokes required to
write a script. Apparently these people have never heard of macros.

Thomas 'PointedEars' Lahn

unread,
Sep 26, 2007, 5:40:33 PM9/26/07
to
Peter Michaux wrote:
> On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:
>> jQuery uses dollar sign variables, which I don't think are allowed
>> under the specification.
>
> Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
> sign is intended for use only in mechanically generated code."

Which is exactly why jQuery should not.

> After reading all the uproar about dollar signs in variables or even
> one character dollar sign variable, I think it would have been better
> if they had left this statement of intention out of the spec. A dollar
> sign can or cannot be in an identifier.

This subsection addresses only identifiers. You missed the point completely.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

Richard Cornford

unread,
Sep 26, 2007, 7:38:13 PM9/26/07
to
Peter Michaux wrote:

> On Sep 26, 1:02 pm, David Mark wrote:
>
>> jQuery uses dollar sign variables, which I don't think are
>> allowed under the specification.
>
> Dollar signs are allowed. See sec 7.6. The spec then says
> "The dollar sign is intended for use only in mechanically
> generated code."

The same is true for Java (indeed it appears that the idea of making
provision for a conventional form to exist for machine generated code
was inspired by the similar convention in Java). You never see Java
programmers using $ symbols in their code, even though not doing so is
no more than a convention. A Java programmer who disregarded that
convention would be derided, but unfortunately a sufficiently large
proportion of javascript 'programmers' are unprofessional (in every
sense of the world) that these faults can seem tolerable.

> After reading all the uproar about dollar signs in variables
> or even one character dollar sign variable, I think it would
> have been better if they had left this statement of intention
> out of the spec.

In that case it would have been better to leave the $ symbol out of the
set of acceptable characters for an Identifier.

> A dollar sign can or cannot be in an identifier.

Just as it can in Java.

> If it can then it is up to the programmer to decide how
> to use it.

Just as it is for Java programmers, but they have more understanding of
their specification, and more appreciation for the value of conventions
in programming.

Ultimately Identifiers provide programmers an opportunity to convey
meaning. The ability to employ words is sufficient for that task, and
letters and some sort of word separator are sufficient for that task.
Conventions can be applied on top of that. For example Hungarian
notation to suggest type in addition to purpose, or camel case to avoid
having to use an explicit word separator, or initial upper case for
'class' names.

The use of the $ symbol does not contribute towards meaning; indeed it
is about the most obscure thing that can appear in an Identifier. And
given that it would not be surprising if the only reason for its
inclusion were to facilitate the specification's stated convention.

> If I was writing JavaScript to last 100 years and knew
> JavaScript would be backwards compatible with the exception
> of new keywords, I would probably start all my identifiers
> with a dollar sign (eg. $foo, $bar) to avoid clashes with
> new keywords.

Doesn't that imply that given a sufficiently long period of time a
programming language will grow an infinite number of keywords? That
seems very unlikely, and quite impractical, as a programmer is unlikely
to be able to learn to use more than a limited set of keywords.

In addition, if a language may grow keywords couldn't it also grow
operators. The $ symbol is already an operator in some languages, so
couldn't those usages migrate into javascript under the same
circumstances?

Richard.

David Mark

unread,
Sep 26, 2007, 7:52:05 PM9/26/07
to
Oops. Went to put this in my own lib and noticed I introduced a silly
mistake when I added the check for documentElement. This check is
probably not needed as browsers that predate getElementsByTagName
aren't likely to have a documentElement, but you never know.

Also added another fallback for ancient browsers that support
document.all (eg IE4.)

var global = this;
var setOpacity = (function() {
var i, l, html;
var doc = global.document;
var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];

if (doc) {
html = (doc.getElementsByTagName)?doc.getElementsByTagName('html')

[0]:doc.documentElement;
if (!html && doc.all && doc.all[0]) {
html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
}
}
if (html && html.style) {
if (typeof html.style.filter != 'undefined') {


return function(el, o) {
var f;
if (el.filters) {
if (el.currentStyle && !el.currentStyle.hasLayout)
{ el.style.zoom = 1; }
f = el.filters.alpha;
if (typeof(f) != 'undefined') {
if (o == 1) {
f.enabled = false;
}
else {
f.enabled = true;
f.opacity = o * 100;
}
}
else {
if (el.style && typeof(el.style.filter) != 'undefined')
{ el.style.filter += "alpha(opacity=" + (o * 100) + ")"; }
}
}
};
}
i = 0;
l = opacityStyles.length;
while (i < l) {

if (typeof(html.style[opacityStyles[i]]) == 'string') {

David Mark

unread,
Sep 26, 2007, 7:53:45 PM9/26/07
to
On Sep 26, 7:52 pm, David Mark <dmark.cins...@gmail.com> wrote:
> Oops. Went to put this in my own lib and noticed I introduced a silly
> mistake when I added the check for documentElement. This check is
> probably not needed as browsers that predate getElementsByTagName
> aren't likely to have a documentElement, but you never know.
>
> Also added another fallback for ancient browsers that support
> document.all (eg IE4.)
>
> var global = this;
> var setOpacity = (function() {
> var i, l, html;
> var doc = global.document;
> var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];
>
> if (doc) {
> html = (doc.getElementsByTagName)?doc.getElementsByTagName('html')
> [0]:doc.documentElement;
> if (!html && doc.all && doc.all[0]) {

Correction:

html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];


Peter Michaux

unread,
Sep 26, 2007, 7:58:01 PM9/26/07
to
On Sep 26, 4:38 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
> Peter Michaux wrote:

> > If I was writing JavaScript to last 100 years and knew
> > JavaScript would be backwards compatible with the exception
> > of new keywords, I would probably start all my identifiers
> > with a dollar sign (eg. $foo, $bar) to avoid clashes with
> > new keywords.
>
> Doesn't that imply that given a sufficiently long period of time a
> programming language will grow an infinite number of keywords?

I don't think I implied that. By using $ at the start of every one of
my identifiers, I'm protected from that one new keyword that clashes.
If I remember correctly, Perl and PHP have made this type of
protection a strict part of the language so that new keywords can be
added without breaking working code.


> That
> seems very unlikely, and quite impractical, as a programmer is unlikely
> to be able to learn to use more than a limited set of keywords.
>
> In addition, if a language may grow keywords couldn't it also grow
> operators. The $ symbol is already an operator in some languages, so
> couldn't those usages migrate into javascript under the same
> circumstances?

If dollar sign becomes an operator in JavaScript then the spec for
allowed identifiers would need to change so that $ is only internal in
an identifier of three or more characters...or something like that.

Peter

Thomas 'PointedEars' Lahn

unread,
Sep 26, 2007, 8:00:21 PM9/26/07
to
Peter Michaux wrote:

> [...] "Richard Cornford" [...] wrote:
>> Peter Michaux wrote:
>>> If I was writing JavaScript to last 100 years and knew
>>> JavaScript would be backwards compatible with the exception
>>> of new keywords, I would probably start all my identifiers
>>> with a dollar sign (eg. $foo, $bar) to avoid clashes with
>>> new keywords.
>> Doesn't that imply that given a sufficiently long period of time a
>> programming language will grow an infinite number of keywords?
>
> I don't think I implied that. By using $ at the start of every one of
> my identifiers, I'm protected from that one new keyword that clashes.

Generally, you are not. There are built-in properties that begin with `$'.
Hence "machine-generated".

Randy Webb

unread,
Sep 26, 2007, 8:21:44 PM9/26/07
to
Thomas 'PointedEars' Lahn said the following on 9/26/2007 5:40 PM:

> Peter Michaux wrote:
>> On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:
>>> jQuery uses dollar sign variables, which I don't think are allowed
>>> under the specification.
>> Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
>> sign is intended for use only in mechanically generated code."
>
> Which is exactly why jQuery should not.

But there is no reason why it *can not* other than people's pedantic
desires to whine about it. Had it been S that was used instead, people
would shut up about it and move on. Except that if it had been S instead
of $ then people would be whining about how the name wasn't an
indication of what it did.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

Richard Cornford

unread,
Sep 26, 2007, 8:39:58 PM9/26/07
to
Randy Webb wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Peter Michaux wrote:
>>> On Sep 26, 1:02 pm, David Mark wrote:
>>>> jQuery uses dollar sign variables, which I don't think
>>>> are allowed under the specification.
>>> Dollar signs are allowed. See sec 7.6. The spec then says
>>> "The dollar sign is intended for use only in mechanically
>>> generated code."
>>
>> Which is exactly why jQuery should not.
>
> But there is no reason why it *can not* other than people's
> pedantic desires to whine about it.

Or to take the same professional attitude toward javascript programming
as any other language deserves.

> Had it been S that was
> used instead, people would shut up about it and move on.
> Except that if it had been S instead of $ then people
> would be whining about how the name wasn't an indication of what it
> did.

Yes they would, and with good reason. Its inherent obscurity is an
excellent reason for not using - S - as the name of some important
function. Using - $ - is making the same mistake, except worse because
the people who started this seem to have done so because - $ - is an
operator in the language that they preferred to javascript, so in
addition to not conveying any meaning in itself (beyond the conventional
meaning, which would be misleading in this case) it is suggesting a
relationship that the functions using the name do not satisfy.

Generally, the place for one letter Identifiers is as local variable
names in functions that are sufficiently small that their declarations
and all of their uses can be simultaneously surveyed. And maybe not even
then.

Richard.

Peter Michaux

unread,
Sep 26, 2007, 8:54:38 PM9/26/07
to
On Sep 26, 5:39 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> Generally, the place for one letter Identifiers is as local variable


> names in functions that are sufficiently small that their declarations
> and all of their uses can be simultaneously surveyed. And maybe not even
> then.


I find it's odd that the Prototype folks like very short API
identifiers but use very long local variable names inside Prototype.

Peter

Peter Michaux

unread,
Sep 26, 2007, 9:07:13 PM9/26/07
to
On Sep 26, 4:38 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

So Java programmers are all instances of the same class?

Peter

Randy Webb

unread,
Sep 26, 2007, 11:28:06 PM9/26/07
to
Richard Cornford said the following on 9/26/2007 8:39 PM:

> Randy Webb wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> Peter Michaux wrote:
>>>> On Sep 26, 1:02 pm, David Mark wrote:
>>>>> jQuery uses dollar sign variables, which I don't think
>>>>> are allowed under the specification.
>>>> Dollar signs are allowed. See sec 7.6. The spec then says
>>>> "The dollar sign is intended for use only in mechanically
>>>> generated code."
>>>
>>> Which is exactly why jQuery should not.
>>
>> But there is no reason why it *can not* other than people's
>> pedantic desires to whine about it.
>
> Or to take the same professional attitude toward javascript programming
> as any other language deserves.

The "Same professional attitude", according to who? And, why did the
argument change from "Because some ECMA.. says so" to a "professional
attitude"? And, your statement implies that anybody that doesn't follow
ECMA - to the letter - isn't a "professional" and that is total hogwash.

>> Had it been S that was
>> used instead, people would shut up about it and move on.
>> Except that if it had been S instead of $ then people
>> would be whining about how the name wasn't an indication of what it did.
>
> Yes they would, and with good reason.

Then why have I never seen the argument "You shouldn't use $ because it
doesn't indicate what the function does" but you see hundreds - if not
thousands - of posts about "You shouldn't do that because some obscure
paragraph in a theoretical document says you shouldn't"?

David Mark

unread,
Sep 26, 2007, 11:42:37 PM9/26/07
to

[snip]

That's what I meant when I said my biggest problem with it is naming
functions "$" or "$$" or anything like that. There's no way to
discern what the functions do without digging them up. Regardless of
the technical merits, it's a stupid idea.

Randy Webb

unread,
Sep 27, 2007, 2:17:15 AM9/27/07
to
David Mark said the following on 9/26/2007 11:42 PM:

Have you perused the function names in the FAQ and the notes page
associated with it? I didn't write the names, only inherited them. What
does StrU do? No cheating and looking, just guess what it does. (It is
in 4.6 though).

Douglas Crockford

unread,
Sep 27, 2007, 10:14:03 AM9/27/07
to
Randy Webb wrote:
> Then why have I never seen the argument "You shouldn't use $ because it
> doesn't indicate what the function does" but you see hundreds - if not
> thousands - of posts about "You shouldn't do that because some obscure
> paragraph in a theoretical document says you shouldn't"?

The ECMAScript Programming Language Standard is the formal standard for the
language. The standard gives clear advice on the intention of $ in identifier
names.

Peter Michaux

unread,
Sep 27, 2007, 11:54:13 AM9/27/07
to

Shouldn't a standard just say what the language can and cannot do?
Imagine the C or Scheme specification suggesting use of indenting and
parens/braces. "Herding cats" comes to mind. Suggesting conventions in
a standard is likely to fail with at least some developers. Those
developers haven't left the standard and so should not be derided. I
think conventions are for the community to develop and adopt if they
suit a particular development project.

Peter

David Mark

unread,
Sep 27, 2007, 1:06:58 PM9/27/07
to

I have no idea what StrU does. Clearly it needs a better name. A
guess? It converts an unsigned integer to a string.

Randy Webb

unread,
Sep 27, 2007, 2:39:41 PM9/27/07
to
Douglas Crockford said the following on 9/27/2007 10:14 AM:

> Randy Webb wrote:
>> Then why have I never seen the argument "You shouldn't use $ because
>> it doesn't indicate what the function does" but you see hundreds - if
>> not thousands - of posts about "You shouldn't do that because some
>> obscure paragraph in a theoretical document says you shouldn't"?
>
> The ECMAScript Programming Language Standard is the formal standard for
> the language.

The only problem with that is that it was written after the fact to try
to describe what was already in place.

> The standard gives clear advice on the intention of $ in identifier names.

Does it also give clear advice on how to name other identifiers? Whoever
decided to put $ in there and nothing else screwed it up.

John G Harris

unread,
Sep 27, 2007, 3:37:50 PM9/27/07
to
On Wed, 26 Sep 2007 at 20:21:44, in comp.lang.javascript, Randy Webb
wrote:

>Thomas 'PointedEars' Lahn said the following on 9/26/2007 5:40 PM:
>> Peter Michaux wrote:
>>> On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:
>>>> jQuery uses dollar sign variables, which I don't think are allowed
>>>> under the specification.
>>> Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
>>> sign is intended for use only in mechanically generated code."
>> Which is exactly why jQuery should not.
>
>But there is no reason why it *can not* other than people's pedantic
>desires to whine about it. Had it been S that was used instead, people
>would shut up about it and move on. Except that if it had been S
>instead of $ then people would be whining about how the name wasn't an
>indication of what it did.


But it's already happened :

Thou shalt not start a global name with "MM_".

Because otherwise there will come a day when you get an obscure bug that
will drive you crazy.

There's a similar rule in C++ about names starting with leading
underlines. The difference is that the rule has been biting people for
years, so competent programmers don't dismiss it as pedantic standards
mania.

John
--
John Harris

Randy Webb

unread,
Sep 27, 2007, 4:31:27 PM9/27/07
to
John G Harris said the following on 9/27/2007 3:37 PM:

> On Wed, 26 Sep 2007 at 20:21:44, in comp.lang.javascript, Randy Webb
> wrote:
>> Thomas 'PointedEars' Lahn said the following on 9/26/2007 5:40 PM:
>>> Peter Michaux wrote:
>>>> On Sep 26, 1:02 pm, David Mark <dmark.cins...@gmail.com> wrote:
>>>>> jQuery uses dollar sign variables, which I don't think are allowed
>>>>> under the specification.
>>>> Dollar signs are allowed. See sec 7.6. The spec then says "The dollar
>>>> sign is intended for use only in mechanically generated code."
>>> Which is exactly why jQuery should not.
>> But there is no reason why it *can not* other than people's pedantic
>> desires to whine about it. Had it been S that was used instead, people
>> would shut up about it and move on. Except that if it had been S
>> instead of $ then people would be whining about how the name wasn't an
>> indication of what it did.
>
>
> But it's already happened :
>
> Thou shalt not start a global name with "MM_".

Or __, ever heard of __doPostBack and the others? All of which are
naming clashes.

> Because otherwise there will come a day when you get an obscure bug that
> will drive you crazy.

That is true with any prefix though. Not just $ or MM or __

> There's a similar rule in C++ about names starting with leading
> underlines. The difference is that the rule has been biting people for
> years, so competent programmers don't dismiss it as pedantic standards
> mania.

Nice to know that about C++ but I don't see the relationship between C++
and/or Java (that Richard brought into it).

Richard Cornford

unread,
Sep 30, 2007, 4:36:30 PM9/30/07
to
Peter Michaux wrote:

> On Sep 27, 7:14 am, Douglas Crockford wrote:
>> Randy Webb wrote:
>>> Then why have I never seen the argument "You shouldn't use $
>>> because it doesn't indicate what the function does" but you
>>> see hundreds - if not thousands - of posts about "You
>>> shouldn't do that because some obscure paragraph in a
>>> theoretical document says you shouldn't"?
>>
>> The ECMAScript Programming Language Standard is the formal
>> standard for the language. The standard gives clear advice
>> on the intention of $ in identifier names.
>
> Shouldn't a standard just say what the language can and
> cannot do?

Failing to state that would result in a poor standard. It would be
unrealistic to expect a standard to never do any more.

> Imagine the C or Scheme specification suggesting use of
> indenting and parens/braces. "Herding cats" comes to mind.

If such a convention was proposed in their respective specification you
may well find programmers of those languages indenting their code.

> Suggesting conventions in a standard is likely to fail
> with at least some developers.

Everything is likely to fail with at least some 'developers', but that
may say more about those 'developers' than anything else.

> Those developers haven't left the standard and so should
> not be derided.

In our case those developers have 'left the standard' and should be
derided. There is no question about what the standard says.

> I think conventions are for the community to develop and
> adopt if they suit a particular development project.

You are not understanding that there are things that cannot be expressed
in the grammar or syntax of a language but may still be seen as
important to the creators of those languages. The way you deal with that
is to include a clear statement of intent in the language's
specification, so that programmers can avoid taking actions that would
undermine that intention. That was a completely successful strategy with
Java, but unfortunately in javascript too many individuals who don't
have a clue about what they are doing are allowed to have too much
influence.

Richard.

Richard Cornford

unread,
Sep 30, 2007, 4:36:33 PM9/30/07
to
Randy Webb wrote:
> Richard Cornford said the following on 9/26/2007 8:39 PM:
>> Randy Webb wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> Peter Michaux wrote:
>>>>> On Sep 26, 1:02 pm, David Mark wrote:
>>>>>> jQuery uses dollar sign variables, which I don't think
>>>>>> are allowed under the specification.
>>>>> Dollar signs are allowed. See sec 7.6. The spec then says
>>>>> "The dollar sign is intended for use only in mechanically
>>>>> generated code."
>>>>
>>>> Which is exactly why jQuery should not.
>>>
>>> But there is no reason why it *can not* other than people's
>>> pedantic desires to whine about it.
>>
>> Or to take the same professional attitude toward javascript
>> programming as any other language deserves.
>
> The "Same professional attitude", according to who?

Apparently according to professionals using every other language with a
similar specification defined convention.

> And, why did the argument change from "Because some
> ECMA.. says so" to a "professional attitude"?

That is not a change. It remains the case that Java programmers do not
break the similar convention that appears in their language
specification, and do not even see a reason for debating that choice.

> And, your statement implies that anybody that doesn't
> follow ECMA - to the letter - isn't a "professional" and
> that is total hogwash.

In the sense that ECMA 262 can be 'followed to the letter' by a
programmer then not doing so would be unprofessional. For any individual
programming javascript there is not a great deal in that document that
can be taken as constituting instructions to do, or not do, anything.
Mostly the document just states how javascript can be expected to
behave.

An example of where ECMA 262 may be taken as providing instructions for
the programmer might be where it states that any attempt to call the -
eval - function indirectly may result in an EvalError, at the discretion
of the implementation. The implication of that statement is that unless
someone is writing for a know set of implementations/versions (where
EvalErrors have been observed not to be thrown) or an implementation
that makes an explicit statement that no such error ever will be thrown,
then authoring with the assumption that no EvalError will ever be thrown
when calling - eval - indirectly (now or in future implementation
versions) would be an obvious mistake and so unprofessional.

>>> Had it been S that was used instead, people would shut
>>> up about it and move on. Except that if it had been S
>>> instead of $ then people would be whining about how the
>>> name wasn't an indication of what it did.
>>
>> Yes they would, and with good reason.
>
> Then why have I never seen the argument "You shouldn't use $
> because it doesn't indicate what the function does" but you
> see hundreds - if not thousands - of posts about "You shouldn't
> do that because some obscure paragraph in a theoretical document
> says you shouldn't"?

If you haven't seen that argument it is because you have not been paying
attention. I have made that point on numerous occasions, and if you go
back to the very first time we discussed this subject you will find that
it was Lasse Reichstein Nielsen's primary reson for rejecting the use of
the - $ - symbol in javascript.

Richard.

Randy Webb

unread,
Oct 3, 2007, 12:59:38 PM10/3/07
to
Richard Cornford said the following on 9/30/2007 4:36 PM:

> Randy Webb wrote:
>> Richard Cornford said the following on 9/26/2007 8:39 PM:
>>> Randy Webb wrote:
>>>> Thomas 'PointedEars' Lahn wrote:
>>>>> Peter Michaux wrote:
>>>>>> On Sep 26, 1:02 pm, David Mark wrote:
>>>>>>> jQuery uses dollar sign variables, which I don't think
>>>>>>> are allowed under the specification.
>>>>>> Dollar signs are allowed. See sec 7.6. The spec then says
>>>>>> "The dollar sign is intended for use only in mechanically
>>>>>> generated code."
>>>>>
>>>>> Which is exactly why jQuery should not.
>>>>
>>>> But there is no reason why it *can not* other than people's
>>>> pedantic desires to whine about it.
>>>
>>> Or to take the same professional attitude toward javascript
>>> programming as any other language deserves.
>>
>> The "Same professional attitude", according to who?
>
> Apparently according to professionals using every other language with a
> similar specification defined convention.

Does that convention extend to function names beginning with uppercase
letters? You should know where that is headed.

<snip>

I snipped the rest of it because I don't care to have this drawn out
conversation again. It has been had in the past and people can search it
out and make up there own minds.

Either way, with regards to $. The only place in ECMAScript that I can
find that it refers to $ is this:

Section 7.6 Identifiers:
<quote>
This standard specifies one departure from the grammar given in the
Unicode standard: The dollar sign ($) and the underscore (_) are
permitted anywhere in an identifier. The dollar sign is intended for use

only in mechanically generated code.

</quote>

It doesn't say "limited" or "required". It simply says "This is what it
is *intended* for". I doubt very seriously that 99% of what is done with
scripting was it's "intended use".

Either way, it doesn't matter what ECMA had to say about it, people are
still going to use it until some UA comes out that breaks it. And no
amount of discussing it in comp.lang.javascript will ever change that.

dhtmlk...@gmail.com

unread,
Oct 5, 2007, 5:13:24 AM10/5/07
to

Things that might seem not to matter:
{OOA&D, Testing, Variable names, comments, code formatting
conventions, process}

These things are just not that appealing to people, generally. This is
especially true for presentation layer development. Why not look at
what toolkit vendors do? They're the rock stars, right?

Yahoo still employs code freezes, status reports, and last time I was
there, my manager would not let me check ANY tests into CVS (they
still don't use SVN). They were calling this Scrum.

Little things like "don't use post-increment operator" are easy for
people to grasp. Free advice that comes with cookies and refreshments.
Serotonin levels go up with the increased blood sugar, jokes are told,
examples are shown (with much hand waving), and people are happy while
not working.

I do wonder though: Why $? I would like to know, out of curiosity, why
did jQuery use $? There is a reason the variable was used; I just
don't know what it is.

The Natural Philosopher

unread,
Oct 5, 2007, 6:04:24 AM10/5/07
to

I would say ha about 90% of "standards" s not so much 'best practice' as
just plain simple 'do it this ways so that people coming upon you
unexpectedly will know what's going on'

E.g. we all drive on one side of the road, but which side is open to debate.

Standards are there mostly for people working together, to enforce a
common style, so everybody knows how things should be done.

Its a mark of the petty jobsworth to elect such standards into moral Laws.

Thomas 'PointedEars' Lahn

unread,
Oct 5, 2007, 9:14:19 AM10/5/07
to
dhtmlk...@gmail.com wrote:
> I do wonder though: Why $? I would like to know, out of curiosity, why
> did jQuery use $? There is a reason the variable was used; I just
> don't know what it is.

Cluelessness. (That was easy.)


PointedEars
--
"Use any version of Microsoft Frontpage to create your site. (This won't
prevent people from viewing your source, but no one will want to steal it.)"
-- from <http://www.vortex-webdesign.com/help/hidesource.htm>

Randy Webb

unread,
Oct 5, 2007, 7:03:43 PM10/5/07
to
Thomas 'PointedEars' Lahn said the following on 10/5/2007 9:14 AM:

> dhtmlk...@gmail.com wrote:
>> I do wonder though: Why $? I would like to know, out of curiosity, why
>> did jQuery use $? There is a reason the variable was used; I just
>> don't know what it is.
>
> Cluelessness. (That was easy.)

And it is debatable who is the one possessing the "Cluelessness".

Why it was used is trivial to figure out.

P.S. YSCIB

--
Randy
Chance Favors The Prepared Mind

Thomas 'PointedEars' Lahn

unread,
Oct 5, 2007, 7:37:04 PM10/5/07
to
Randy Webb wrote:
> Thomas 'PointedEars' Lahn said the following on 10/5/2007 9:14 AM:
>> dhtmlk...@gmail.com wrote:
>>> I do wonder though: Why $? I would like to know, out of curiosity, why
>>> did jQuery use $? There is a reason the variable was used; I just
>>> don't know what it is.
>> Cluelessness. (That was easy.)
>
> And it is debatable who is the one possessing the "Cluelessness".

Not understood.

> Why it was used is trivial to figure out.

Then you can tell it for sure, yes?

> P.S. YSCIB

-v


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Randy Webb

unread,
Oct 6, 2007, 1:19:21 AM10/6/07
to
Thomas 'PointedEars' Lahn said the following on 10/5/2007 7:37 PM:

> Randy Webb wrote:
>> Thomas 'PointedEars' Lahn said the following on 10/5/2007 9:14 AM:
>>> dhtmlk...@gmail.com wrote:
>>>> I do wonder though: Why $? I would like to know, out of curiosity, why
>>>> did jQuery use $? There is a reason the variable was used; I just
>>>> don't know what it is.
>>> Cluelessness. (That was easy.)
>> And it is debatable who is the one possessing the "Cluelessness".
>
> Not understood.

Try enabling the spell checker in Thunderbird. It might shed some light
on it.

>> Why it was used is trivial to figure out.
>
> Then you can tell it for sure, yes?

Sure I can. It was chosen because of the uniqueness of it and the lack
of use of it on the web. What better way to pick a simple single
character identifier than one that wasn't in use?

Thomas 'PointedEars' Lahn

unread,
Oct 6, 2007, 7:53:19 AM10/6/07
to
Randy Webb wrote:
> Thomas 'PointedEars' Lahn said the following on 10/5/2007 7:37 PM:
>> Randy Webb wrote:
>>> Thomas 'PointedEars' Lahn said the following on 10/5/2007 9:14 AM:
>>>> dhtmlk...@gmail.com wrote:
>>>>> I do wonder though: Why $? I would like to know, out of curiosity, why
>>>>> did jQuery use $? There is a reason the variable was used; I just
>>>>> don't know what it is.
>>>> Cluelessness. (That was easy.)
>>> And it is debatable who is the one possessing the "Cluelessness".
>> Not understood.
>
> Try enabling the spell checker in Thunderbird. It might shed some light
> on it.

It merely shows that you don't know the word and that it isn't in the
default dictionary of Thunderbird's spell checker.

>>> Why it was used is trivial to figure out.
>> Then you can tell it for sure, yes?
>
> Sure I can.

You can *not*, you are not the author.

> It was chosen because of the uniqueness of it and the lack
> of use of it on the web.

Logical fallacy: wishful thinking. You can know neither whether or not it
was used on the Web at the time the library was conceived, nor can you know
that supposed uniqueness or supposed no-use at the time was the reason for
choosing it.

> What better way to pick a simple single character identifier than one
> that wasn't in use?

Logical fallacy: non sequitur.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

Randy Webb

unread,
Oct 6, 2007, 3:22:43 PM10/6/07
to
Thomas 'PointedEars' Lahn said the following on 10/6/2007 7:53 AM:

> Randy Webb wrote:
>> Thomas 'PointedEars' Lahn said the following on 10/5/2007 7:37 PM:
>>> Randy Webb wrote:
>>>> Thomas 'PointedEars' Lahn said the following on 10/5/2007 9:14 AM:
>>>>> dhtmlk...@gmail.com wrote:
>>>>>> I do wonder though: Why $? I would like to know, out of curiosity, why
>>>>>> did jQuery use $? There is a reason the variable was used; I just
>>>>>> don't know what it is.
>>>>> Cluelessness. (That was easy.)
>>>> And it is debatable who is the one possessing the "Cluelessness".
>>> Not understood.
>> Try enabling the spell checker in Thunderbird. It might shed some light
>> on it.
>
> It merely shows that you don't know the word and that it isn't in the
> default dictionary of Thunderbird's spell checker.

<eyeroll> You still don't get it. I didn't expect you to though.

>>>> Why it was used is trivial to figure out.
>>> Then you can tell it for sure, yes?
>> Sure I can.
>
> You can *not*, you are not the author.

You need to get out into the real world more often Thomas.

dhtmlk...@gmail.com

unread,
Oct 13, 2007, 2:30:13 AM10/13/07
to
On Sep 26, 1:29 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
> David Mark wrote:
> > I've got a collection of functions that accept a function
> > or object (paired with a method name) as a callback.
>
> > For the longest time I have relied on this test.
>
> > (typeof cb == 'function')
>
> > This should work as well, but I am not sure how well it
> > degrades in older browsers.
>
> The typeof operator is consistent when its subjects are not host
> objects, and has been around since JavaScript 1.1, so well pre-dating
> the 4th generation browsers.
>
> > I think there are issues with functions created in
> > another context (eg frame) as well.
>
> > (cb instanceof Function)
>
> Yes, the a Function constructor exists for each frame and each has
> unique identity. That is also true of the Array constructor.
>
> > Then I came across this.
>
> > (!!fn && typeof fn != "string" && !fn.nodeName &&
> > fn.constructor != Array && /function/i.test( fn + "" ))
>
> > I'm sure it is wrong
>
> That would depend on what you considered correct. It looks like the
> subject of the test is expected to be any of a javascript function
> (unwisely tested), a siring primitive, a DOM element and Array or a
> value with falseness. Getting into a position where it is necessary to
> make such a test betrays very poor code design.
>
I think you meant "portrays" not "betrays". Am I right?

That analysis would be right if they'd used ||, but they used &&.

I provided analysis of the problem on my site. The problem is that
this function returns true for objects (of any type) that contain
"function" in the toString result.
(!!fn )....................falses are out.
(typeof fn != "string")....string values are out
(!fn.nodeName).............things with a truthy nodeName are out.
(fn.constructor != Array)..Arrays in same frame are out.
(/function/i.test( fn + "" ).anything else left can get through, it
just has to say "function".


It's not safe, but it's indicative of the problem of typechecking in
js.

Dojo has similar stuff. They claim that some built-in functions don't
return "function" for typeof. I have been unable to prove that
statement true.

http://dhtmlkitchen.com/?category=/JavaScript/&date=2007/10/10/&entry=How-to-Tell-if-an-Object-is-a-Function

> There are no circumstances under which a function object would result
> in - typeof fn != 'string' - being true

No. typeof fn != 'string' should *always* be true.

or its having a - nodeName -
> property or a constructor property that was a reference to the frame's
> Array constructor (unless they had been explicitly added).
>
You're confused by thinking ||. The function uses &&

Anyway, typechecking is an issue and this post made me think about
that, which led to the blog entry.

> > as it is from jQuery, but it makes me wonder if
> > there are bugs in older browsers that will mislead
> > my test.
>
> What makes you think that jQuery, or any of its like, was written with
> any interest in, or knowledge of, 'older browsers'?
>
> > As an aside, I was looking at the jQuery source as some
> > browser sniffer I was arguing with on a blog cited it as
> > part of an "everybody is doing it" argument.
>
> If that was a valid argument we would not have seen the virtual
> disappearance of people using - eval - to reference object properties
> with constructed dot notation property accessors. There was a time when
> "everybody" was doing that, but most have now learnt better.
>
> > I had glanced at it previously and dismissed
> > it based on its resemblance to Prototype. Upon closer
> > inspection, it makes Prototype look inspired. Suffice
> > to say that anybody who recommends it hasn't read the
> > code. It's a horror show.
>
You know, it might not be very good code, but I think John might be
creative. He's interested in these things, so improvement is
inevitable.


> The code above speaks of poor design, but at least it is ECMA 262
> conforming, so that is one up on Prototype.js.
>
What is not conforming in Prototype? I haven't done a thorough
analysis on it.

> Richard.


Thomas 'PointedEars' Lahn

unread,
Oct 13, 2007, 5:41:15 AM10/13/07
to
dhtmlk...@gmail.com wrote:
> On Sep 26, 1:29 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
> wrote:
>> David Mark wrote:
>>> Then I came across this.
>>> (!!fn && typeof fn != "string" && !fn.nodeName &&
>>> fn.constructor != Array && /function/i.test( fn + "" ))
>>> I'm sure it is wrong
>> That would depend on what you considered correct. It looks like the
>> subject of the test is expected to be any of a javascript function
>> (unwisely tested), a siring primitive, a DOM element and Array or a
>> value with falseness. Getting into a position where it is necessary to
>> make such a test betrays very poor code design.
>>
> I think you meant "portrays" not "betrays". Am I right?
>
> That analysis would be right if they'd used ||, but they used &&.
>
> I provided analysis of the problem on my site. The problem is that
> this function returns true for objects (of any type) that contain
> "function" in the toString result.
> (!!fn )....................falses are out.

(fn) is equivalent there.

> (typeof fn != "string")....string values are out
> (!fn.nodeName).............things with a truthy nodeName are out.
> (fn.constructor != Array)..Arrays in same frame are out.
> (/function/i.test( fn + "" ).anything else left can get through, it
> just has to say "function".
>
> It's not safe, but it's indicative of the problem of typechecking in
> js.

No, it is indicative of the bad quality of the calling script, and
ultimately of the bad quality of the called script. As Richard said,
one should never get into a position where a test of that form would
be necessary.

The code comes from jQuery (1.2.1):

// This may seem like some crazy code, but trust me when I say that this
// is the only cross-browser way to do this. --John
isFunction: function( fn ) {
return !!fn && typeof fn != "string" && !fn.nodeName &&
fn.constructor != Array && /function/i.test( fn + "" );
}

jQuery claims to support IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+ (and
calls that "cross-browser" -- OMG). But, if

/function/i.test(fn + "")

would return `true', it is highly unlikely that

typeof fn

would yield "string", so the test

typeof fn != "string"

is unnecessary. Unless, of course, someone who lacks the minimum clue
assumes that strings could be called and so could ever be subject to
isFunction().

Furthermore, if

/function/i.test(fn + "")

would return `true', how could it be that

fn.constructor != Array

could not yield `true' and therefore that test would be unnecessary as well?
There is yet a script engine to be named that does not type-convert an array
object to string in the form "element1,element2,element3". Unless, of
course, someone who lacks a minimum clue assumes that Array objects having
references to callable objects as elements could be called as well and so
could ever be subject to isFunction() in which case the former test would
return `true' (as the string representation of such an Array object could be
"...,function ...() {....},...").

Needless to say that RegExp.prototype.test() already type-converts its
argument to string (see ECMAScript Ed. 3, 15.10.6.3) and so the forced
conversion by concatenation is unnecessary.

And a Function object, being a native object, certainly could have a
user-defined property `nodeName' and still could be called. So that test
makes no sense as well.

So far methods of built-in objects have always yielded typeof "function",
only methods of host objects in the MSHTML DOM have yielded typeof "object".

Therefore,

if (/\b(function|object)\b/i.test(typeof fn) && fn)
{
// ...
}

should satisfy all the reasonable cases in which isFunction() could be called:

- False-values could only yield `object', as `null' does, but they would not
type-convert to `true';

- typeof fn == "string" is already excluded (unless one assumes the
improbable case that `typeof' would yield "string function" and the like);

- fn.constructor != Array could only yield `true' because typeof "function"
would apply;

- /function/i.test( fn + "" ) could only yield `true' because typeof
"function" or "object" would apply.

And none of the obscure testing in jQuery is explained as to why it was done
(i.e. for what script engine and DOM); we have only the word of "John" that
it would be "the only cross-browser way to do this."

BTW: jQuery-1.2.1.js is served for download from Google Code with
Content-Type: text/x-c. OMG.


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

dhtmlk...@gmail.com

unread,
Oct 13, 2007, 8:17:55 PM10/13/07
to
On Oct 13, 2:41 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> dhtmlkitc...@gmail.com wrote:
> > On Sep 26, 1:29 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
> > wrote:
> >> David Mark wrote:
> >>> Then I came across this.
> >>> (!!fn && typeof fn != "string" && !fn.nodeName &&
> >>> fn.constructor != Array && /function/i.test( fn + "" ))
> >>> I'm sure it is wrong
> >> That would depend on what you considered correct. It looks like the
> >> subject of the test is expected to be any of a javascriptfunction
> >> (unwisely tested), a siring primitive, a DOM element and Array or a
> >> value with falseness. Getting into a position where it is necessary to
> >> make such a test betrays very poor code design.
>
> > I think you meant "portrays"not"betrays". Am I right?
>
> > That analysis would be right if they'd used ||, but they used &&.
>
> > I provided analysis of the problem on my site. The problem is that
> > thisfunctionreturns true for objects (of any type) that contain

> > "function" in the toString result.
> > (!!fn )....................falses are out.
>
> (fn) is equivalent there.
>
> > (typeof fn != "string")....string values are out
> > (!fn.nodeName).............things with a truthy nodeName are out.
> > (fn.constructor != Array)..Arrays in same frame are out.
> > (/function/i.test( fn + "" ).anything else left can get through, it
> > just has to say "function".
>
> > It'snotsafe, but it's indicative of the problem of typechecking in

> > js.
>
> No, it is indicative of the bad quality of the calling script, and
> ultimately of the bad quality of the called script. As Richard said,
> one should never get into a position where a test of that form would
> be necessary.
>
how can you know if it's a function?

typeof fn? nope, not in safari.

document.links, document.getElementsByTagName("blah")

Safari thinks they implement call, which is what typeof checks for.

> The code comes from jQuery (1.2.1):
>
> // This may seem like some crazy code, but trust me when I say that this
> // is the only cross-browser way to do this. --John
> isFunction:function( fn ) {
> return !!fn && typeof fn != "string" && !fn.nodeName &&
> fn.constructor != Array && /function/i.test( fn + "" );
> }
>
> jQuery claims to support IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+ (and
> calls that "cross-browser" -- OMG). But, if
>
> /function/i.test(fn + "")
>
> would return `true', it is highly unlikely that
>
> typeof fn
>
> would yield "string", so the test
>
> typeof fn != "string"
>
> is unnecessary. Unless, of course, someone who lacks the minimum clue
> assumes that strings could be called and so could ever be subject to
> isFunction().
>

No, it excludes strings.

"function" + "" would return true. This clause prevents that.


> Furthermore, if
>
> /function/i.test(fn + "")
>
> would return `true', how could it be that
>
> fn.constructor != Array
>

var a = Array{function bork(){});


> couldnotyield `true' and therefore that test would be unnecessary as well?
No.


> There is yet a script engine to be named that doesnottype-convert an array


> object to string in the form "element1,element2,element3". Unless, of
> course, someone who lacks a minimum clue assumes that Array objects having
> references to callable objects as elements could be called as well and so
> could ever be subject to isFunction() in which case the former test would
> return `true' (as the string representation of such an Array object could be
> "...,function...() {....},...").
>

Yes.

> Needless to say that RegExp.prototype.test() already type-converts its
> argument to string (see ECMAScript Ed. 3, 15.10.6.3) and so the forced
> conversion by concatenation is unnecessary.
>

That's true, but being explicit is a good thing.

> And aFunctionobject, being a native object, certainly could have a


> user-defined property `nodeName' and still could be called. So that test
> makes no sense as well.
>

Right, so could any of the four examples on my site.

> So far methods of built-in objects have always yielded typeof "function",
> only methods of host objects in the MSHTML DOM have yielded typeof "object".
>
> Therefore,
>
> if (/\b(function|object)\b/i.test(typeof fn) && fn)
> {
> // ...
> }
>
> should satisfy all the reasonable cases in which isFunction() could be called:
>

Relying on toString is bad duck typing. It quacks but dosn't walk.
It's the same thinking that went into the jQuery and Dojo code.

> - False-values could only yield `object', as `null' does, but they wouldnot
> type-convert to `true';
>
> - typeof fn == "string" is already excluded (unless one assumes the
> improbable case that `typeof' would yield "stringfunction" and the like);
>

new String()
{toString:function(){return 'function';}}

a = Function();
a.toString = "widget";

> - fn.constructor != Array could only yield `true' because typeof "function"
> would apply;
>

frames.

> - /function/i.test( fn + "" ) could only yield `true' because typeof
> "function" or "object" would apply.
>
> And none of the obscure testing in jQuery is explained as to why it was done
> (i.e. for what script engine and DOM); we have only the word of "John" that
> it would be "the only cross-browser way to do this."
>

RIght. No detail, no tests.

Dojo and YUI at least has comments. Unfortunately, a lot of the the
time, the comments are contradictory.

The Dojo example I posted on my site. isAlien is weird. I think
they're trying to test Host objects, but the comment says built-in,
and the code tests the input for a string value of [native code]/i,
which could be anything.

String values do not imply an object's type. Relying on toString is
not safe.

Garrett

> PointedEars
> --

Richard Cornford

unread,
Oct 13, 2007, 10:01:33 PM10/13/07
to
Randy Webb wrote:
> Richard Cornford said the following on 9/30/2007 4:36 PM:
>> Randy Webb wrote:
>>> Richard Cornford said the following on 9/26/2007 8:39 PM:
>>>> Randy Webb wrote:
>>>>> Thomas 'PointedEars' Lahn wrote:
>>>>>> Peter Michaux wrote:
>>>>>>> On Sep 26, 1:02 pm, David Mark wrote:
>>>>>>>> jQuery uses dollar sign variables, which I don't think
>>>>>>>> are allowed under the specification.
>>>>>>> Dollar signs are allowed. See sec 7.6. The spec then says
>>>>>>> "The dollar sign is intended for use only in mechanically
>>>>>>> generated code."
>
>>>>>> Which is exactly why jQuery should not.
>
>>>>> But there is no reason why it *can not* other than people's
>>>>> pedantic desires to whine about it.
>
>>>> Or to take the same professional attitude toward javascript
>>>> programming as any other language deserves.
>
>>> The "Same professional attitude", according to who?
>
>> Apparently according to professionals using every other language
>> with a similar specification defined convention.
>
> Does that convention extend to function names beginning with
> uppercase letters?

The specification has nothing to say on the subject of the
capitalisation of Identifiers. Conventions relating to that subject are
left to the individual programmer (or their employers) to choose. The
convention of capitalising 'class' names is adopted from Java, and can
be very helpful if you are writing anything OO, but other capitalisation
conventions have been proposed (even if they haven't really caught on).

> You should know where that is headed.

No, but I can guess.

> <snip>
> I snipped the rest of it because I don't care to have this drawn
> out conversation again. It has been had in the past and people can
> search it out and make up there own minds.
>
> Either way, with regards to $. The only place in ECMAScript that
> I can find that it refers to $ is this:
>
> Section 7.6 Identifiers:
> <quote>
> This standard specifies one departure from the grammar given in
> the Unicode standard: The dollar sign ($) and the underscore (_)
> are permitted anywhere in an identifier. The dollar sign is
> intended for use only in mechanically generated code.
> </quote>
>
> It doesn't say "limited" or "required".

It is not possible for it to say limited or required. The syntax for an
Identifier has to be correct regardless of whether the code was machine
generated or not.

> It simply says "This is what it is *intended* for".

Yes, and that answers the question of why a character has been included
in the set of characters permissible in an Identifier when that
character contributes nothing to the task of identifying.

> I doubt very seriously that 99% of
> what is done with scripting was it's "intended use".

If computer programming languages have an intended use then it should be
to be used to program computers.

> Either way, it doesn't matter what ECMA had to say about it,

It does matter.

> people are still going to use it

You mean use it incorrectly. Using $ symbols in machine generated
identifiers could not be subject to any criticism.

> until some UA comes out that breaks it.

A UA could not break it without the end result not being ECMAScript
compatible. The browsers have no way of knowing whether the code they
get is machine generated or not and have no reason to care. This is
entirely a question for programmers, like most conventions. It just
happens to be a convention proposed at the point of defining the
language rather than something arising in the use of the language (such
as indenting styles and capitalisation conventions).

> And no amount of discussing it in comp.lang.javascript
> will ever change that.

I wouldn't necessarily bet on that. A good few years of heavily
criticising the use of - eval - for evaluating dot notation property
accessors (and explaining/discussing the alternatives) has seen that
practice almost disappear (and certainly disappear from anything
professionally authored). It may be that a sufficiently robust attitude
taken towards this bad practice for sufficiently long will see it go the
same way as the worst examples of - eval - abuse. Things in the wider
world do change under the influence of our discussions, albeit slowly.

Richard.

Richard Cornford

unread,
Oct 13, 2007, 10:01:00 PM10/13/07
to
<dhtmlk...@gmail.com> wrote:
> On Sep 26, 1:29 am, Richard Cornford wrote:
<snip>

>> > Then I came across this.
>>
>> > (!!fn && typeof fn != "string" && !fn.nodeName &&
>> > fn.constructor != Array && /function/i.test( fn + "" ))
>>
>> > I'm sure it is wrong
>>
>> That would depend on what you considered correct. It looks
>> like the subject of the test is expected to be any of a
>> javascript function (unwisely tested), a siring primitive,
>> a DOM element and Array or a value with falseness. Getting
>> into a position where it is necessary to make such a test
>> betrays very poor code design.
>>
> I think you meant "portrays" not "betrays". Am I right?

No, "betrays" says exactly what I intended to say.

> That analysis would be right if they'd used ||, but they
> used &&.

No, that analysis is correct because it uses &&.

> I provided analysis of the problem on my site.

That is not what I would call it. It is a pity that you choose to
publish such things without first having them checked by someone who
knows this subject.

> The problem is that this function returns true for
> objects (of any type) that contain
> "function" in the toString result.

It also may return false for object that are functions. The author is
clearly unsure about what it is that is being tested for, and so has no
criteria for identifying an effective test for that (if one exists).

> (!!fn )....................falses are out.

A pointless test if the subject is not expected to potentially be a
value that has falseness.

> (typeof fn != "string")....string values are out

A pointless test if the subject is not expected to potentially be a
string primitive.

> (!fn.nodeName).............things with a truthy nodeName are out.

A pointless test if the subject is not expected to potentially be an
object with a true nodeName property. An expected characteristic of DOM
elements.

> (fn.constructor != Array)..Arrays in same frame are out.

A pointless test if the subject is not expected to potentially be an
Array.

> (/function/i.test( fn + "" ).anything else left can get
> through, it just has to say "function".

So in what sense is my "analysis" not correct? "It looks like the


subject of the test is expected to be any of a javascript function
(unwisely tested), a siring primitive, a DOM element and Array or a

value with falseness".

> It's not safe, but it's indicative of the problem of
> typechecking in js.
>
> Dojo has similar stuff.

The dojo version of isFunction is nearly as bad as it will also return
true for non-callable objects. Again the authors appear to be uncertain
of what it is they are testing for.

> They claim that some built-in functions don't
> return "function" for typeof.

They can claim anything they like, but if it were a true statement they
could state the environment in which this was the case and show a test
case that proves the point (or shows where their misconceptions lie).
Without that, and judging their competence by the code in dojo, I would
not trust them to have made an accurate analysis.

> I have been unable to prove that
> statement true.

<snip>

You should not need to. The person making the claim is the one
responsible for demonstrating it.

>> There are no circumstances under which a function object would result
>> in - typeof fn != 'string' - being true
>
> No. typeof fn != 'string' should *always* be true.

Yes, it looks like I omitted a "not" between "being" and "true". One of
the consequences of rushing to get it posted before going to work on a
week day.

> or its having a - nodeName -
>> property or a constructor property that was a reference to the
>> frame's
>> Array constructor (unless they had been explicitly added).
>>
> You're confused by thinking ||. The function uses &&

No I am not. To get a true result with the logical AND operation test
every individual sub-expression needs to evaluate to true.

> Anyway, typechecking is an issue

Not really. Once you get used to properly employing a loosely typed
language it rapidly becomes a non-issue, and such testing is relegated
to the feature testing role alone. Hence my assertion that the test
betrays poor design. Before someone has the experience to cope with
loose typing they will be struggling to identify the types of things
from a position of being totally in the dark. This results in such
testing functions being passed almost anything at all, and so having to
jump through hoops applying tests that really should never be necessary.

<snip>


>>> I had glanced at it previously and dismissed
>>> it based on its resemblance to Prototype. Upon closer
>>> inspection, it makes Prototype look inspired. Suffice
>>> to say that anybody who recommends it hasn't read the
>>> code. It's a horror show.
>>
> You know, it might not be very good code, but I think John
> might be creative.

Being "creative", of itself, is of little significance. Masses of
dubiously code and all of those half-ass hacks were 'created' by
someone.

To be usefully creative it is necessary to first formulate a clear
notion of what it is that is to be achieved. It is evidence of this
clarity of comprehension that is absent from the testing code. Hence my
assertion that the test betrays poor design. Before someone has the
experience to cope with loose typing they will be struggling to identify
the types of things from a position of being totally in the dark. This
results in such testing functions being passed almost anything at all,
and so having to jump through hoops applying tests that really should
never be necessary.

> He's interested in these things, so improvement is
> inevitable.

That may be likely, but not inevitable. It appears that becoming
satisfied with what you have done can seriously inhibit an ability to
improve.

>> The code above speaks of poor design, but at least it is
>> ECMA 262 conforming, so that is one up on Prototype.js.
>>
> What is not conforming in Prototype?

<snip>

ECMS 262 provides an EvalError that is to be thrown when the - eval -
function is called indirectly (in any way other than as - eval(
seomthing ); - ). It then gives implementations the option of not
throwing that exception. ECMAScript conforming code has no choice but
assume the worst case (that the exception will be thrown), while
Prototype.js makes the assumption that no implications will (ever) throw
that exception. Thus it sacrifices ECMAScript compatibility (and so all
hope of its ever being cross-browser) and ends up being dependent upon a
limited set of known (current) implications where the exception can be
observed not to be thrown.

Richard.

Richard Cornford

unread,
Oct 13, 2007, 10:28:20 PM10/13/07
to
<dhtmlk...@gmail.com> wrote:
> On Oct 13, 2:41 am, Thomas 'PointedEars' Lahn wrote:
>> dhtmlkitc...@gmail.com wrote:
<snip>

>>> It'snotsafe, but it's indicative of the problem of typechecking in
>>> js.
>>
>> No, it is indicative of the bad quality of the calling script, and
>> ultimately of the bad quality of the called script. As Richard said,
>> one should never get into a position where a test of that form would
>> be necessary.
>>
> how can you know if it's a function?

First define what you mean by "a function".

> typeof fn? nope, not in safari.

Are you certain? Is it really the case that objects that return
'function' from a typeof operation cannot be called? Or are you just not
expecting them to be callable? Have you actually tried calling the
objects that safari asserts are functions?

> document.links, document.getElementsByTagName("blah")
>
> Safari thinks they implement call, which is what typeof
> checks for.

<snip>

One of the consequences of using imprecise terminology is that when you
say "call" nobody knows whether you mean [[Call]] or
Function,.prototype.call. It is the implementing of the internal
[[Call]] method that typeof should be interested in, though not
necessarily for host objects. NodeLists and HTMLCollection interface
implementing objects would be host obejcts.

Richard.

Randy Webb

unread,
Oct 13, 2007, 11:10:14 PM10/13/07
to
Richard Cornford said the following on 10/13/2007 10:28 PM:

> <dhtmlk...@gmail.com> wrote:
>> On Oct 13, 2:41 am, Thomas 'PointedEars' Lahn wrote:
>>> dhtmlkitc...@gmail.com wrote:
> <snip>
>>>> It'snotsafe, but it's indicative of the problem of typechecking in
>>>> js.
>>>
>>> No, it is indicative of the bad quality of the calling script, and
>>> ultimately of the bad quality of the called script. As Richard said,
>>> one should never get into a position where a test of that form would
>>> be necessary.
>>>
>> how can you know if it's a function?
>
> First define what you mean by "a function".
>
>> typeof fn? nope, not in safari.
>
> Are you certain? Is it really the case that objects that return
> 'function' from a typeof operation cannot be called? Or are you just not
> expecting them to be callable? Have you actually tried calling the
> objects that safari asserts are functions?

Can I ask you to first define what you mean by "called" or "callable"?

>> document.links, document.getElementsByTagName("blah")
>>
>> Safari thinks they implement call, which is what typeof
>> checks for.
> <snip>
>
> One of the consequences of using imprecise terminology is that when you
> say "call" nobody knows whether you mean [[Call]] or
> Function,.prototype.call. It is the implementing of the internal
> [[Call]] method that typeof should be interested in, though not
> necessarily for host objects. NodeLists and HTMLCollection interface
> implementing objects would be host obejcts.

So document.images should be a Host Object? Safari3/Win reports
typeof(document.images) as 'function'. All other Windows based browsers
I have report it as 'object'.

dhtmlk...@gmail.com

unread,
Oct 13, 2007, 11:58:00 PM10/13/07
to
On Oct 13, 7:01 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> <dhtmlkitc...@gmail.com> wrote:
> > On Sep 26, 1:29 am, Richard Cornford wrote:
> <snip>
> >> > Then I came across this.
>
> >> > (!!fn && typeof fn != "string" && !fn.nodeName &&
> >> > fn.constructor != Array && /function/i.test( fn + "" ))
>
> >> > I'm sure it is wrong
>
> >> That would depend on what you considered correct. It looks
> >> like the subject of the test is expected to be any of a
> >> javascript function (unwisely tested), a siring primitive,
> >> a DOM element and Array or a value with falseness. Getting
> >> into a position where it is necessary to make such a test
> >> betrays very poor code design.
>
> > I think you meant "portrays" not "betrays". Am I right?
>
> No, "betrays" says exactly what I intended to say.
>
> > That analysis would be right if they'd used ||, but they
> > used &&.
>
> No, that analysis is correct because it uses &&.
>
> > I provided analysis of the problem on my site.
>
> That is not what I would call it. It is a pity that you choose to
> publish such things without first having them checked by someone who
> knows this subject.
>

There you go again.

The subject is expected NOT to be any of those things.

The point of each test is to exclude these things. Just maybe, there's
some type of node that says it's a "function" to typeof. It's actually
likely in Safari; Safari thinks document.images is a function, which
it is Not!

Now I should clear up a bit of confusion you posted on the webkit bug:

Take an object that is an instance of an NodeList.

That object's constructor implements NodeList. The object itself is an
object. The fact that it is callable is a bug, copied from MSIE, who
made document.all, et c. a function, e.g. document.all(0). Mozilla
copied this. It is retarded, IMO.

javascript:alert(Function.prototype.call.call(document.links,document,
1))

Not really useful. OR good design.

An instance of a NodeList is NOT the object that implements NodeList.
The object that implement's NodeList is the instance's constructor.

> > It's not safe, but it's indicative of the problem of
> > typechecking in js.
>
> > Dojo has similar stuff.
>
> The dojo version of isFunction is nearly as bad as it will also return
> true for non-callable objects.

What objects are those? Only ones that incorrectly report "function"
for typeof, I hope.

What I prefer about the dojo function is at least it is less
inclusive. It filters out with the typeof operator.

document.links instanceof Function; // false in Safari.

That's what I'm saying. If jQuery's isFunction gets a falsish value, a
string value, et c, that value is excluded. It's "none of", not "any
of". You're wrong.


> > Anyway, typechecking is an issue
>
> Not really. Once you get used to properly employing a loosely typed
> language it rapidly becomes a non-issue, and such testing is relegated
> to the feature testing role alone. Hence my assertion that the test
> betrays poor design. Before someone has the experience to cope with
> loose typing they will be struggling to identify the types of things
> from a position of being totally in the dark. This results in such
> testing functions being passed almost anything at all, and so having to
> jump through hoops applying tests that really should never be necessary.
>

http://www.m-w.com/dictionary/betray

I'm pretty sure you meant "betrays good design," as that's the gist of
what you're saying.

> <snip>
>
> >>> I had glanced at it previously and dismissed
> >>> it based on its resemblance to Prototype. Upon closer
> >>> inspection, it makes Prototype look inspired. Suffice
> >>> to say that anybody who recommends it hasn't read the
> >>> code. It's a horror show.
>
> > You know, it might not be very good code, but I think John
> > might be creative.
>
> Being "creative", of itself, is of little significance. Masses of
> dubiously code and all of those half-ass hacks were 'created' by
> someone.
>
> To be usefully creative it is necessary to first formulate a clear
> notion of what it is that is to be achieved. It is evidence of this
> clarity of comprehension that is absent from the testing code. Hence my
> assertion that the test betrays poor design. Before someone has the
> experience to cope with loose typing they will be struggling to identify
> the types of things from a position of being totally in the dark. This
> results in such testing functions being passed almost anything at all,
> and so having to jump through hoops applying tests that really should
> never be necessary.
>

When I use others' code, I want it to fail right away if I use it
wrong. Now it might have been my fault for passing in an undefined,
but hey, I'm human and I lose my keys, I've put shit in the washer
that shouldn't go there, (phone, et c).

When others use my code it should fail fast and report the error
properly.

Now if some library had a function that takes a callback, that would
be when you want to know "is the callback a function?"

function doStuff( errorHandler ) {

}

When will errorHandler be invoked? Maybe never, right? Or maybe it
will be invoked some time after deployment, maybe even after I'm gone
from the job. Wow, that would suck.

Wouldn't it make sense to check the errorHandler 'thing' and make sure
it's actually a function first?


function doStuff( errorHandler ) {
if(typeof errorHandler != "function") "
var err = new Error("hey stoopid...");
log(err);
throw err;
...
}

> > He's interested in these things, so improvement is
> > inevitable.
>
> That may be likely, but not inevitable. It appears that becoming
> satisfied with what you have done can seriously inhibit an ability to
> improve.
>
> >> The code above speaks of poor design, but at least it is
> >> ECMA 262 conforming, so that is one up on Prototype.js.
>
> > What is not conforming in Prototype?
>
> <snip>
>
> ECMS 262 provides an EvalError that is to be thrown when the - eval -
> function is called indirectly (in any way other than as - eval(
> seomthing ); - ). It then gives implementations the option of not
> throwing that exception. ECMAScript conforming code has no choice but
> assume the worst case (that the exception will be thrown), while
> Prototype.js makes the assumption that no implications will (ever) throw
> that exception. Thus it sacrifices ECMAScript compatibility (and so all
> hope of its ever being cross-browser) and ends up being dependent upon a
> limited set of known (current) implications where the exception can be
> observed not to be thrown.
>

OK.

Garrett

> Richard.


David Mark

unread,
Oct 14, 2007, 1:06:09 AM10/14/07
to
On Oct 13, 10:28 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
[snip]

> Are you certain? Is it really the case that objects that return
> 'function' from a typeof operation cannot be called? Or are you just not
> expecting them to be callable? Have you actually tried calling the
> objects that safari asserts are functions?

The objects that Safari claims are functions are indeed callable.
They have the internal [[Call]] method, but do not implement
Function.prototype.call.

Here are two test functions that are similar to the function I
referred to in the original post. One is ambiguous in what it expects
and one is not.

// Ambiguous version
// cb parameter can be a Function or other type of Object (explicitly
excluding a null object)
// method must be a string and is required if cb is not a Function

function executeCB1(cb, arg, method) {
if (typeof cb == 'function') { // disambiguation
return cb(arg);
}
else {
if (typeof cb[method] == 'function') { // validation
return cb[method](arg);
}
}
}

// Unambiguous version
// cb must be a Function
// context is optional

function executeCB2(cb, arg, context) {
if (typeof cb == 'function') { // validation
if (typeof context == 'undefined') {
return cb(arg);
}
else {
if (typeof cb.call == 'function') { // validation
return cb.call(context, arg);
}
}
}
}

function callbackFunction(a) {
return a;
}

function CallbackObject(b) {
this.callback = function(b) { return b; };
}

var co = new CallbackObject;

alert(executeCB1(callbackFunction, 'test function'));
alert(executeCB1(co, 'test object', 'callback'));

alert(executeCB2(callbackFunction, 'test function'));
alert(executeCB2(co.callback, 'test object', co));

alert(executeCB1(document.images, 'testimg'));
alert(executeCB2(document.images, 'testimg'));
alert(executeCB2(document.images, 'testimg', co));

The expected results were returned by all but Windows Safari Beta:

test function
test object
test function
test object
undefined
undefined
undefined

Safari returns:

test function
test object
test function
test object
[Object HTMLImageElement]
[Object HTMLImageElement]
undefined

So the validation is enough to prevent errors, but not enough to
maintain consistent results for the test cases. The pattern is clear
though.

function isFunction(f) {
return (typeof f == 'function' && typeof f.call == 'function');
}

function executeCB1(cb, arg, method) {
if (isFunction(cb)) { // disambiguation
return cb(arg);
}
else {
if (isFunction(cb[method])) { // validation
return cb[method](arg);
}
}
}

function executeCB2(cb, arg, context) {
if (isFunction(cb)) { // validation
if (typeof context == 'undefined') {
return cb(arg);
}
else {
if (isFunction(cb.call)) { // validation
return cb.call(context, arg);
}
}
}
}

The revised versions bring Windows Safari (and the like) into line.

David Mark

unread,
Oct 14, 2007, 2:03:27 AM10/14/07
to
On Oct 13, 11:58 pm, "dhtmlkitc...@gmail.com" <dhtmlkitc...@gmail.com>
wrote:

>
> The subject is expected NOT to be any of those things.
>
> The point of each test is to exclude these things. Just maybe, there's
> some type of node that says it's a "function" to typeof. It's actually
> likely in Safari; Safari thinks document.images is a function, which
> it is Not!

Technically, it is not a Function, but it does implement an internal
[[Call]] method, so it is a function.

>
> Now I should clear up a bit of confusion you posted on the webkit bug:
>
> Take an object that is an instance of an NodeList.
>
> That object's constructor implements NodeList. The object itself is an
> object. The fact that it is callable is a bug, copied from MSIE, who
> made document.all, et c. a function, e.g. document.all(0). Mozilla
> copied this. It is retarded, IMO.

Microsoft? Retarded? Who knew? Of course, Mozilla (and Opera)
didn't need to copy this behavior.

>
> javascript:alert(Function.prototype.call.call(document.links,document,
> 1))
>
> Not really useful. OR good design.

Agreed.

[snip]


>
> That's what I'm saying. If jQuery's isFunction gets a falsish value, a
> string value, et c, that value is excluded. It's "none of", not "any
> of". You're wrong.

I think Richard was saying that the confused logic in this low-level
function is indicative of higher-level problems in the design. For
example, a higher-level function designed to receive an array of DOM
elements and/or functions, which in turn passes them to the isFunction
function to determine which are which.

[snip]

>
> When I use others' code, I want it to fail right away if I use it
> wrong. Now it might have been my fault for passing in an undefined,
> but hey, I'm human and I lose my keys, I've put shit in the washer
> that shouldn't go there, (phone, et c).

That is a matter of exception handling. Whether it fails silently or
loudly, the logic in the isFunction function is confused, the author's
"trust me" comment is of little comfort and the two combined would
seem to indicate a design flaw in the library. Even if that is not
the case, the library is trash as it requires useragent sniffing just
to support a handful of modern browsers.

Thomas 'PointedEars' Lahn

unread,
Oct 14, 2007, 4:24:09 AM10/14/07
to
dhtmlk...@gmail.com wrote:
> On Oct 13, 2:41 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> wrote:
>> The code comes from jQuery (1.2.1):
>>
>> // This may seem like some crazy code, but trust me when I say that this
>> // is the only cross-browser way to do this. --John
>> isFunction:function( fn ) {
>> return !!fn && typeof fn != "string" && !fn.nodeName &&
>> fn.constructor != Array && /function/i.test( fn + "" );
>> }
>>
>> jQuery claims to support IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+ (and
>> calls that "cross-browser" -- OMG). But, if
>>
>> /function/i.test(fn + "")
>>
>> would return `true', it is highly unlikely that
>>
>> typeof fn
>>
>> would yield "string", so the test
>>
>> typeof fn != "string"
>>
>> is unnecessary. Unless, of course, someone who lacks the minimum clue
>> assumes that strings could be called and so could ever be subject to
>> isFunction().
>
> No, it excludes strings.

Which is unnecessary, as strings could never be called, and so should never
be subject to the isFunction() test method.

> "function" + "" would return true. This clause prevents that.

But can you name a case where a callable object would evaluate as a string
containing "function" without type conversion?

>> Furthermore, if
>>
>> /function/i.test(fn + "")
>>
>> would return `true', how could it be that
>>
>> fn.constructor != Array
>
> var a = Array{function bork(){});

But that assumes that `a' could be called which it cannot be. Hence it
should not be subject to an isFunction() test. An array is not a function.

>> couldnotyield `true'

Again, I did not write it that way. Please stop using broken software.

> > and therefore that test would be unnecessary as well?
> No.

Yes.

>> Needless to say that RegExp.prototype.test() already type-converts its
>> argument to string (see ECMAScript Ed. 3, 15.10.6.3) and so the forced
>> conversion by concatenation is unnecessary.
>
> That's true, but being explicit is a good thing.

Being explicit would be

/.../.test(String(...))

But that would be nonsense as well, as it would decrease efficiency.
Because if the specification algorithm is followed, type conversion
to String would happen *twice* in both cases: first due to the source
code and the second time as step 1 of RegExp.prototype.exec().

>> And aFunctionobject, being a native object, certainly could have a
>> user-defined property `nodeName' and still could be called. So that
>> test makes no sense as well.
>
> Right, so could any of the four examples on my site.

I didn't care about your (Web?) site and I have no intention to do so. If
you have arguments to present, please do it here.

>> - False-values could only yield `object', as `null' does, but they wouldnot
>> type-convert to `true';
>>
>> - typeof fn == "string" is already excluded (unless one assumes the
>> improbable case that `typeof' would yield "stringfunction" and the like);
>
> new String()
> {toString:function(){return 'function';}}

This is assuming that a String object could be called and so should/could


ever be subject to isFunction().

> a = Function();
> a.toString = "widget";

What should this accomplish? Overwriting the toString() method with a
string value renders type conversion to string non-functional. And even
if you meant

a = Function();
a.toString = function() { return "widget"; };

`typeof a' still would yield "function". The flaw in the described
algorithm is that it does not use `typeof' first. Because if it did,
many tests would not be necessary and the algorithm as a whole would
be less obscure and less error-prone.

>> - fn.constructor != Array could only yield `true' because typeof "function"
>> would apply;
>
> frames.

I don't see any argument here.

> String values do not imply an object's type. Relying on toString is
> not safe.

Exactly.


PointedEars

Thomas 'PointedEars' Lahn

unread,
Oct 14, 2007, 4:33:17 AM10/14/07
to
Randy Webb wrote:
> So document.images should be a Host Object?

A host object, yes. It has always referred to one.

> Safari3/Win reports typeof(document.images) as 'function'. All other
> Windows based browsers I have report it as 'object'.

And have you tested whether or not it can be called?

But again, you have been testing with a *beta version* (and, even more, the
beta version of *the first version for that platform and operating system
ever*), so any test results you got do not qualify for a argument regarding
software design.

It can be taken under serious consideration from the moment on the release
version shows the same result.

Richard Cornford

unread,
Oct 14, 2007, 11:18:42 AM10/14/07
to
Randy Webb wrote:
> Richard Cornford said the following on 10/13/2007 10:28 PM:
>> <dhtmlk...@gmail.com> wrote:
>>> On Oct 13, 2:41 am, Thomas 'PointedEars' Lahn wrote:
>>>> dhtmlkitc...@gmail.com wrote:
>> <snip>
>>>>> It'snotsafe, but it's indicative of the problem of
>>>>> typechecking in js.
>>>>
>>>> No, it is indicative of the bad quality of the calling script,
>>>> and ultimately of the bad quality of the called script. As
>>>> Richard said, one should never get into a position where a
>>>> test of that form would be necessary.
>>>>
>>> how can you know if it's a function?
>>
>> First define what you mean by "a function".
>>
>>> typeof fn? nope, not in safari.
>>
>> Are you certain? Is it really the case that objects that
>> return 'function' from a typeof operation cannot be
>> called? Or are you just not expecting them to be callable?
>> Have you actually tried calling the objects that safari
>> asserts are functions?
>
> Can I ask you to first define what you mean by "called"
> or "callable"?

No more than sticking an ArgumentsList after a reference to the object
(the 'call operator', with or without arguments). That is what I would
consider calling an object, and to be callable that abject should not
throw an exception as a direct result of its being called (though it may
still throw an exception in response to its arguments'' values, as that
would be behaviour passed the point of calling it and so unrelated to
its callability).

>>> document.links, document.getElementsByTagName("blah")
>>>
>>> Safari thinks they implement call, which is what typeof
>>> checks for.
>> <snip>
>>
>> One of the consequences of using imprecise terminology is that
>> when you say "call" nobody knows whether you mean [[Call]] or
>> Function,.prototype.call. It is the implementing of the internal
>> [[Call]] method that typeof should be interested in, though not
>> necessarily for host objects. NodeLists and HTMLCollection
>> interface implementing objects would be host obejcts.
>
> So document.images should be a Host Object?

It must be a host object, as it is provided by the host's object model.

> Safari3/Win reports typeof(document.images) as 'function'.

Apparently.

> All other Windows based browsers I have report it as 'object'.

Maybe, but that is neither necessarily true of windows based browsers
nor historically common on Mac browsers. Even Mac IE 5 would report
'function' in this context, and on Windows you only have to go back a
few Opera versions to see the same there.

(Incidentally, I will be replying to your e-mail soonish, but I will
have to do some research first so probably not for a day or two.)

Richard.

Richard Cornford

unread,
Oct 14, 2007, 11:18:53 AM10/14/07
to
David Mark wrote:

> On Oct 13, 10:28 pm, Richard Cornford wrote:
> [snip]
>
>> Are you certain? Is it really the case that objects that return
>> 'function' from a typeof operation cannot be called? Or are you
>> just not expecting them to be callable? Have you actually tried
>> calling the objects that safari asserts are functions?
>
> The objects that Safari claims are functions are indeed callable.
> They have the internal [[Call]] method, but do not implement
> Function.prototype.call.

Which is also true of built in functions such as - parseInt - (by
specification).

<snip>


> test function
> test object
> test function
> test object
> undefined
> undefined
> undefined
>
> Safari returns:
>
> test function
> test object
> test function
> test object
> [Object HTMLImageElement]
> [Object HTMLImageElement]
> undefined
>
> So the validation is enough to prevent errors, but not
> enough to maintain consistent results for the test cases.

But the results are still correct for all of those browsers. The -
document.images - object can be called in Safari and calling it has a
predictable outcome.

> The pattern is clear though.
>
> function isFunction(f) {
> return (typeof f == 'function' && typeof f.call == 'function');
> }

Now you are starting to narrow down on what you mean by 'a function'.
You have excluded the built in functions and are being left with just
programmer defined functions and methods. If that is the discrimination
you want to make then you have a test for that. The problems with all
the previous examples of - isFunction - is that there authors have not
worked out what the discrimination they are trying to make is, and so
are creating functions with pretty much arbitrary outcomes.

<snip>


> The revised versions bring Windows Safari (and the like) into line.

It is worth pointing out (again) that historically it is absolutely
normal for objects implementing NodeList, HTMLCollection and pretty much
any other collection interface to be both callable and to return
'function' form a - typeof - test. This was true for Mac IE, Opera
versions at least up to 7.nn, Konqueror, IceBrowsr up to 5 and probably
many others. Safari is not doing anything unusual or unexpected here so
Safari's behaviour is against the expectations of anyone then it is
those expectations that are at fault.

Richard.

Richard Cornford

unread,
Oct 14, 2007, 11:18:47 AM10/14/07
to
<dhtmlk...@gmail.com> wrote:

> On Oct 13, 7:01 pm, Richard Cornford wrote:
>> <dhtmlkitc...@gmail.com> wrote:
>>> On Sep 26, 1:29 am, Richard Cornford wrote:
>> <snip>
>>>>> Then I came across this.
>>
>>>>> (!!fn && typeof fn != "string" && !fn.nodeName &&
>>>>> fn.constructor != Array && /function/i.test( fn + "" ))
>>
>>>>> I'm sure it is wrong
>>
>>>> That would depend on what you considered correct. It looks
>>>> like the subject of the test is expected to be any of a
>>>> javascript function (unwisely tested), a siring primitive,
>>>> a DOM element and Array or a value with falseness. Getting
>>>> into a position where it is necessary to make such a test
>>>> betrays very poor code design.
>>
>> > I think you meant "portrays" not "betrays". Am I right?
>>
>> No, "betrays" says exactly what I intended to say.
>>
>>> That analysis would be right if they'd used ||, but they
>>> used &&.
>>
>> No, that analysis is correct because it uses &&.
>>
>>> I provided analysis of the problem on my site.
>>
>> That is not what I would call it. It is a pity that you choose
>> to publish such things without first having them checked by
>> someone who knows this subject.
>
> There you go again.

And there you go again. Instead of being interested in why I think 50%
of what you wrote is somewhere between uninformed and nonsense you would
rather disregard the comment and leave it as it is.

<snip>


>>> (!!fn )....................falses are out.
>>
>> A pointless test if the subject is not expected to potentially
>> be a value that has falseness.
>>
>>> (typeof fn != "string")....string values are out
>>
>> A pointless test if the subject is not expected to potentially
>> be a string primitive.
>>
>>> (!fn.nodeName).............things with a truthy nodeName are out.
>>
>> A pointless test if the subject is not expected to potentially
>> be an object with a true nodeName property. An expected
>> characteristic of DOM elements.
>>
>>> (fn.constructor != Array)..Arrays in same frame are out.
>>
>> A pointless test if the subject is not expected to potentially
>> be an Array.
>>
>>> (/function/i.test( fn + "" ).anything else left can get
>>> through, it just has to say "function".
>>
>> So in what sense is my "analysis" not correct? "It looks like the
>> subject of the test is expected to be any of a javascript function
>> (unwisely tested), a siring primitive, a DOM element and Array or a
>> value with falseness".
>>
> The subject is expected NOT to be any of those things.

If the subject (the value that is subject to the tests) were not
expected to be a string what would be the point of seeing how the
results of - typeof - compared with 'string'? If it could not be a
string then the outcome would be known at the point of writing the code
and no runtime test would be required. The same goes for every other
test.

> The point of each test is to exclude these things.

If the subject of the test is not expected to potentially be the things
that are excluded there is no point making any effort to exclude them.

> Just maybe, there's
> some type of node that says it's a "function" to typeof.

There is nothing to say that an object implementing the Node interface
should not be a function object.

> It's actually likely in Safari; Safari thinks document.images
> is a function, which it is Not!

Fist you must state what it is that defined 'a function'. One completely
rational and justifiable definition of 'a function' in ECMAScritp terms
could be "an object that can be called" (i.e. subject to the 'call
operator' without that act of itself directly resulting in an exception
being thrown (later exceptions, such as winging about the types or
number of arguments are not related to the callability of the object)).
Under that definition Safari's - document.images - is a function, as it
can be called.

> Now I should clear up a bit of confusion you posted on the
> webkit bug:
>
> Take an object that is an instance of an NodeList.

NodeList is an interface not a 'class'. Which is a good thing, as
ECMAscript/javascript has no notion of 'classes'. But even in
class-based languages like Java an object implementing an interface is
not necessarily an object of any particular (or any single) class.

Javascript is a very flexible language and it loves interfaces. You can
take an object, any object, and retro-fit an interface to it at runtime.
And you can add the interface to any number of objects with very diverse
origins to the extent that they have nothing else in common that could
be regarded as asserting their 'type'.

The result is that any notion of "an instance of an NodeList" has very
little meaning in javascript. It may or may not reflect an internal
implementation detail, but beyond that it is no more than a perception
in the mind of a programmer.

> That object's constructor implements NodeList.

Absolutely nothing, anywhere, makes any assertions about constructors in
relation to object that implement the NodeList interface.

> The object itself is an object.

An object implementing the NodeList interface must be an object, but is
not required to be anything more. And it can be expected to be a host
object, so almost nothing else can be asserted about it with authority.

> The fact that it is callable is a bug,

No. Object can be callable. At least the things that are callable in
javascript are all objects.

> copied from MSIE, who made document.all, etc. a function,


> e.g. document.all(0). Mozilla copied this.

And copied by nearly every other browser since, with a significant
proportion of them also returning 'function' from - typeof - operations
on those objects.

> It is retarded, IMO.

It is certainly unnecessary and unhelpful, but it is (and has for some
considerable time been) a reality.

> javascript:alert(Function.prototype.call.call(
> document.links,document, 1))


>
> Not really useful. OR good design.
>
> An instance of a NodeList is NOT the object that
> implements NodeList.

An object that implements the NodeList interface is precisely what the
W3C DOM specifications define it as. Making any assertion beyond that
would be technically groundless.

> The object that implement's NodeList is the instance's
> constructor.

Can you find any authorities statement supporting that assertion?
Neither of the applicable documents (Core DOM and its ECMAScript
bindings and ECMA 262) are that big so it should not take too long to
look.

>>> It's not safe, but it's indicative of the problem of
>>> typechecking in js.
>>
>>> Dojo has similar stuff.
>>
>> The dojo version of isFunction is nearly as bad as it will
>> also return true for non-callable objects.
> What objects are those?

Objects that inherit from functions.

> Only ones that incorrectly report "function"
> for typeof, I hope.

Have you identifier any objects that do "incorrectly" report 'function'?
We have seen that the objects that are concerning you are callable
(which would be a fine justification for reporting 'function') and that
they are host objects (so they may report anything at all). Where does
your definition of "incorrectly" come from?

> What I prefer about the dojo function

This is the dojo function:-

| if(dojo.isBrowser && dojo.isSafari){
| // only slow this down w/ gratuitious casting in Safari since
| // it's what's b0rken
| dojo.isFunction = function(/*anything*/ it){
| if((typeof(it) == "function") && (it == "[object NodeList]")){
| return false;
| }
| return (typeof it == "function" || it instanceof Function);
| }
| }else{
| dojo.isFunction = function(/*anything*/ it){
| return (typeof it == "function" || it instanceof Function);
| }
| }

> is at least it is less inclusive.
> It filters out with the typeof operator.
>
> document.links instanceof Function; // false in Safari.

But it will include any non-function object that has a function on its
prototype chain, so the objects that are 'isFunction' are not
necessarily even executable. It makes you wonder what it is they think
they are testing for.

<snip>


>>> You're confused by thinking ||. The function uses &&
>>
>> No I am not. To get a true result with the logical AND operation
>> test every individual sub-expression needs to evaluate to true.
>>
> That's what I'm saying. If jQuery's isFunction gets a falsish value,
> a string value, et c, that value is excluded. It's "none of", not
> "any of". You're wrong.

No I am right. If the subject of the test (the value that is tested)
were not expected to be any of those possibilities then there would be
no point in testing them with the intention of excluding them.

>>> Anyway, typechecking is an issue
>>
>> Not really. Once you get used to properly employing a loosely
>> typed language it rapidly becomes a non-issue, and such testing
>> is relegated to the feature testing role alone. Hence my assertion
>> that the test betrays poor design. Before someone has the
>> experience to cope with loose typing they will be struggling to
>> identify the types of things from a position of being totally in
>> the dark. This results in such testing functions being passed
>> almost anything at all, and so having to jump through hoops
>> applying tests that really should never be necessary.
>>
> http://www.m-w.com/dictionary/betray
>
> I'm pretty sure you meant "betrays good design," as that's the
> gist of what you're saying.

It is in the nature of bad design that it attempts to hide. Here the bad
design has been exposed by the test code. The bad design has been
betrayed by the code and so its attempt to hide from observation has
been unsuccessful. Thus the test code betrays the bad design.

<snip>


> When I use others' code, I want it to fail right away if I use it
> wrong. Now it might have been my fault for passing in an undefined,
> but hey, I'm human and I lose my keys, I've put shit in the washer
> that shouldn't go there, (phone, et c).
>
> When others use my code it should fail fast and report the error
> properly.
>
> Now if some library had a function that takes a callback, that would
> be when you want to know "is the callback a function?"

It would be better to have some more precise definition of what you
meant by 'a function' here. Do you just mean something that can be
called, or do you really want to discriminate between programmer defined
functions and everything else? Pinning down precisely what you need to
know is a necessary pre-requisite of designing an effective test that
will tell you that.

> function doStuff( errorHandler ) {
>
> }
>
> When will errorHandler be invoked? Maybe never, right?

That would depend on your testing. Including an error handler and then
not testing whether it handled the errors correctly would seem reckless
to me.

> Or maybe it will be invoked some time after deployment, maybe
> even after I'm gone from the job. Wow, that would suck.

So you would write code for a job and then walk away without testing
that it worked as designed?

> Wouldn't it make sense to check the errorHandler 'thing' and
> make sure it's actually a function first?
>
>
> function doStuff( errorHandler ) {
> if(typeof errorHandler != "function") "
> var err = new Error("hey stoopid...");
> log(err);
> throw err;
> ...
> }

Not as much sense as deliberately provoking the error in testing and so
knowing that it did work.

>>> He's interested in these things, so improvement is
>>> inevitable.
>>
>> That may be likely, but not inevitable. It appears that becoming
>> satisfied with what you have done can seriously inhibit an
>> ability to improve.

<snip>

Richard.

Randy Webb

unread,
Oct 14, 2007, 1:47:46 PM10/14/07
to
Richard Cornford said the following on 10/14/2007 11:18 AM:

That would imply, to me anyway, that Safari (even in Beta form) gets it
right and all other browsers I tested it on get it wrong. Would that be
a correct assumption?

>>>> document.links, document.getElementsByTagName("blah")
>>>>
>>>> Safari thinks they implement call, which is what typeof
>>>> checks for.
>>> <snip>
>>>
>>> One of the consequences of using imprecise terminology is that
>>> when you say "call" nobody knows whether you mean [[Call]] or
>>> Function,.prototype.call. It is the implementing of the internal
>>> [[Call]] method that typeof should be interested in, though not
>>> necessarily for host objects. NodeLists and HTMLCollection
>>> interface implementing objects would be host obejcts.
>>
>> So document.images should be a Host Object?
>
> It must be a host object, as it is provided by the host's object model.
>
>> Safari3/Win reports typeof(document.images) as 'function'.
>
> Apparently.
>
>> All other Windows based browsers I have report it as 'object'.
>
> Maybe, but that is neither necessarily true of windows based browsers
> nor historically common on Mac browsers. Even Mac IE 5 would report
> 'function' in this context, and on Windows you only have to go back a
> few Opera versions to see the same there.

Then Safari is right and IE/FF/Opera are wrong?

I am not trying to get into an argument about it, just curious about it.
Never really had a need to test whether something was a function or not,
I usually know without doubt whether I wrote it or not :)

> (Incidentally, I will be replying to your e-mail soonish, but I will
> have to do some research first so probably not for a day or two.)

Take your time. I would rather have a thought out reply than a hasty one.

Thomas 'PointedEars' Lahn

unread,
Oct 14, 2007, 2:00:03 PM10/14/07
to
Randy Webb wrote:
> Richard Cornford said the following on 10/14/2007 11:18 AM:
>> Randy Webb wrote:
>>> Richard Cornford said the following on 10/13/2007 10:28 PM:
>>>> <dhtmlk...@gmail.com> wrote:
>>>>> typeof fn? nope, not in safari.
>>>> Are you certain? Is it really the case that objects that
>>>> return 'function' from a typeof operation cannot be
>>>> called? Or are you just not expecting them to be callable?
>>>> Have you actually tried calling the objects that safari
>>>> asserts are functions?
>>> Can I ask you to first define what you mean by "called"
>>> or "callable"?
>> No more than sticking an ArgumentsList after a reference to the object
>> (the 'call operator', with or without arguments). That is what I would
>> consider calling an object, and to be callable that abject should not
>> throw an exception as a direct result of its being called (though it may
>> still throw an exception in response to its arguments'' values, as that
>> would be behaviour passed the point of calling it and so unrelated to
>> its callability).
>
> That would imply, to me anyway, that Safari (even in Beta form) gets it
> right and all other browsers I tested it on get it wrong. Would that be
> a correct assumption?

Not at all. With host objects, all bets are off. And as long as objects
that can't be called do not yield `function' or `object', there is no problem.

>>> All other Windows based browsers I have report it as 'object'.
>> Maybe, but that is neither necessarily true of windows based browsers
>> nor historically common on Mac browsers. Even Mac IE 5 would report
>> 'function' in this context, and on Windows you only have to go back a
>> few Opera versions to see the same there.
>
> Then Safari is right and IE/FF/Opera are wrong?

It is not a matter of right and wrong.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

Randy Webb

unread,
Oct 14, 2007, 2:46:12 PM10/14/07
to
Thomas 'PointedEars' Lahn said the following on 10/14/2007 2:00 PM:

Is there any thing in scripting that isn't an Object though? That part
is confusing to me. I thought any and everything was an Object, at least
underneath, and that functions were merely augmented Objects. That
implies to me that anything and everything should return object or some
subset of object.

>>>> All other Windows based browsers I have report it as 'object'.
>>> Maybe, but that is neither necessarily true of windows based browsers
>>> nor historically common on Mac browsers. Even Mac IE 5 would report
>>> 'function' in this context, and on Windows you only have to go back a
>>> few Opera versions to see the same there.
>> Then Safari is right and IE/FF/Opera are wrong?
>
> It is not a matter of right and wrong.

Thank you.

Richard Cornford

unread,
Oct 14, 2007, 3:15:28 PM10/14/07
to
Randy Webb wrote:
> Richard Cornford said the following on 10/14/2007 11:18 AM:
>> Randy Webb wrote:
<snip>

>>> Can I ask you to first define what you mean by "called"
>>> or "callable"?
>>
>> No more than sticking an ArgumentsList after a reference to
>> the object (the 'call operator', with or without arguments).
>> That is what I would consider calling an object, and to be
>> callable that abject should not throw an exception as a direct
>> result of its being called (though it may still throw an
>> exception in response to its arguments'' values, as that would be
>> behaviour passed the point of calling it and so
>> unrelated to its callability).
>
> That would imply, to me anyway, that Safari (even in Beta form)
> gets it right

It is more a matter of what safari is doing is not in any way incorrect.
It could do much else instead and still not be doing anything incorrect.
Generally I am inclined to think that when at object can be called it
makes perfect sense for - typeof - to report 'function', even if with
host objects there is nothing to say that they should.

> and all other browsers I tested it on get it wrong.

They are not getting it wrong, as there is nothing to define what would
qualify as 'correct' in this context. Some of those browsers are doing
something that is a little irrational in having a callable object but
reporting 'object' with - typeof -, but they either are Windows IE or
are imitating Windows IE in some of its more irrational behaviour.

Remember that on Windows IE all the DOM methods, and functions such as
alert and setTimeout also report 'object' from - typeof -, so it is at
least consistently irrational.

> Would that be a correct assumption?

There are no grounds for expecting any particular outcome so there are
no criteria for correct or incorrect.

<snip>


>>> All other Windows based browsers I have report it as
>> 'object'.
>>
>> Maybe, but that is neither necessarily true of windows based
>> browsers nor historically common on Mac browsers. Even Mac
>> IE 5 would report 'function' in this context, and on Windows
>> you only have to go back a few Opera versions to see the same
>> there.
>
> Then Safari is right and IE/FF/Opera are wrong?

<snip>

On firefox (and all previous Mozilla/gecko browsers) you could not call
the collection objects, so reporting 'object' from - tyepof - is a
rational action. Windows IE is just doing the same as it always has
done, and Opera has recently changed to imitate the behaviour of Windows
IE (previously it did report 'function'). I don't approve of that change
but I can understand why it has happened.

Richard.

Thomas 'PointedEars' Lahn

unread,
Oct 14, 2007, 3:20:14 PM10/14/07
to
Randy Webb wrote:
> Thomas 'PointedEars' Lahn said the following on 10/14/2007 2:00 PM:
>> Randy Webb wrote:
>>> [Safari 3 Beta for Windows yields typeof document.images == "function"]

>>> That would imply, to me anyway, that Safari (even in Beta form) gets it
>>> right and all other browsers I tested it on get it wrong. Would that be
>>> a correct assumption?
>> Not at all. With host objects, all bets are off. And as long as objects
>> that can't be called do not yield `function' or `object', there is no problem.
>
> Is there any thing in scripting that isn't an Object though?

There is, but see below.

> That part is confusing to me. I thought any and everything was an Object,

It's not, but I hope that this value-object duality will be resolved
eventually in favor of "everything is an object" with ES 4. (As much
as I hope the wave-particle duality in quantum mechanics will be
resolved some time soon, only that the former is more probable :))

> at least underneath,

If you mean by that when a method is used on a primitive value this value
can be type-converted into a corresponding object, then you are correct:

"bla".charAt(0)
(12.41).toFixed(1)

> and that functions were merely augmented Objects.

Functions/methods are special objects that can be called and inherit from
Object.prototype.

> That implies to me that anything and everything should return object or
> some subset of object.

The `typeof' operator is well-defined in ES 3 Final, 11.4.3, which includes
the provision for implementations that they yield *any* value on that
operation for host objects:

| 5. Return a string determined by Type(Result(4)) according to the
| following table:
|
| Type Result
| ---------------------------------
| Undefined "undefined"
| Null "object"
| Boolean "boolean"
| Number "number"
| String "string"
|
| Object (native and "object"
| doesn’t implement
| [[Call]])
|
| Object (native and "function"
| implements [[Call]])
|
| Object (host) Implementation-dependent
^^^^^^^^^^^^^^^^^^^^^^^^

Fortunately for us developers, implementors so far have chosen to have
their implementations yield only "function" or "object" then (CMIIW).

Thomas 'PointedEars' Lahn

unread,
Oct 14, 2007, 3:23:02 PM10/14/07
to
Thomas 'PointedEars' Lahn wrote:

> Randy Webb wrote:
>> and that functions were merely augmented Objects.
>
> Functions/methods are special objects that can be called and inherit from
> Object.prototype.

D'oh. Make that Function.prototype.

David Mark

unread,
Oct 14, 2007, 9:16:31 PM10/14/07
to
On Oct 14, 11:18 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
[snip]

>
> This is the dojo function:-
>
> | if(dojo.isBrowser && dojo.isSafari){
> | // only slow this down w/ gratuitious casting in Safari since
> | // it's what's b0rken
> | dojo.isFunction = function(/*anything*/ it){
> | if((typeof(it) == "function") && (it == "[object NodeList]")){
> | return false;
> | }
> | return (typeof it == "function" || it instanceof Function);
> | }
> | }else{
> | dojo.isFunction = function(/*anything*/ it){
> | return (typeof it == "function" || it instanceof Function);
> | }
> | }
>

It is useful to note that Dojo (along with jQuery) was cited as an
example of a "major library" that implements browser sniffing, in a
misguided attempt to justify browser sniffing as a viable technique.

Clearly the author(s) have assumed that Safari is the only agent that
is "b0rken" in this way (and that their isSafari method is a reliable
indication of a Safari browser.) As noted, the forks that follow
raise questions about what this code is supposed to do. It also casts
serious doubt about the veracity of functions built atop it.

So the browser sniffer who cited this mess as an example is justifying
his own incompetence by comparing it to other peoples' less-than-
competent output. The fact that lots of developers use these
libraries is cited as proof that they are a worthwhile comparison.
The "argument" is circular as users of jQuery, Dojo, Prototype, etc.
know only what they hear from the "experts" who churn out the
libraries. The "experts" conclude that since so many less-than-expert
developers listen to them, they must be on the right track. Tell
either side they are wrong and they cite the other.

Peter Michaux

unread,
Nov 2, 2007, 1:01:29 PM11/2/07
to
Hi David,

On Sep 26, 4:52 pm, David Mark <dmark.cins...@gmail.com> wrote:

> var global = this;
> var setOpacity = (function() {
> var i, l, html;
> var doc = global.document;
> var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];


Did you test the "KhtmlOpacity" property on early version of Safari
yourself? I have not and have also seen it written as "KHTMLOpacity"
and "KHtmlOpacity".

Peter

Matt Kruse

unread,
Nov 26, 2007, 1:41:09 PM11/26/07
to
On Oct 14, 9:18 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> Fist you must state what it is that defined 'a function'. One completely
> rational and justifiable definition of 'a function' in ECMAScritp terms
> could be "an object that can be called"

Bringing this thread back from the dead...

Is there a way to reliably check whether I can call an object as a
function?

For example, in IE6:
var input = document.createElement("input");
input.type = "text";
document.body.appendChild( input );
var prop = "focus";
alert(typeof input[prop]); // object
alert(typeof input[prop].call); // undefined
input[prop](); // works

What test could I do to ensure that the last line will never cause an
error, no matter what the value of "prop" is, and still work correctly
for things like "focus"? Is it possible?

I know the argument can be made that this is bad design to not know
whether or not you're passing in something that can be called as a
function. But I'm asking as a purely technical question, whether or
not it's possible.

Matt Kruse

Richard Cornford

unread,
Nov 26, 2007, 2:54:39 PM11/26/07
to
Matt Kruse wrote:

> On Oct 14, 9:18 am, Richard Cornford wrote:
>> Fist you must state what it is that defined 'a function'. One
>> completely rational and justifiable definition of 'a function'
>> in ECMAScritp terms could be "an object that can be called"
>
> Bringing this thread back from the dead...
>
> Is there a way to reliably check whether I can call an object
> as a function?

Not if you want to include methods of host objects in the set of objects that could be called.
You might reasonably say that if - typeof x - was 'function' then it would be safe to call the
object, and be correct in all the environments that I have ever encountered. But we both know
that would mean never calling host methods on Windows IE, which would be somewhat disappointing.

<snip>


> I know the argument can be made that this is bad design
> to not know whether or not you're passing in something
> that can be called as a function.

Absolutely.

> But I'm asking as a purely technical question, whether or
> not it's possible.

Not possible in the general case. Possibly a case fro try-catch and handling the errors. Or
avoid the problem by designing the issue out of the system.

Richard.

VK

unread,
Nov 26, 2007, 3:43:19 PM11/26/07
to

In "standard" clj terms ("it is not possible for 100% - it is not
possible at all") it is not possible.

The evident way is to use typeof:
if (typeof something == 'function') {
}

but in IE some/many native methods of window or document are reported
as "object" instead of "function" despite still can be used in [Call]
context.

try {
something();
}
catch(e) {
}

is another way but "there can be UAs that don't support blah-blah"

So the answer is: it is possible for any current practical extend but
it is not possible as an absolutely bulletproof solution.
To call it "possible" or "not possible" is up to you.

Matt Kruse

unread,
Nov 26, 2007, 4:21:06 PM11/26/07
to
On Nov 26, 1:54 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> You might reasonably say that if - typeof x - was 'function' then it would be safe to call the
> object, and be correct in all the environments that I have ever encountered.

Unfortunately, in Firefox:

var o = document.createElement("object");
alert(typeof o); // "function"
o(); // ERROR

Btw, earlier in this thread there was a complaint about jQuery's lack
of explanation for its code and lack of test cases, so I thought I
would point this out:
http://dev.jquery.com/browser/trunk/jquery/test/unit/core.js#L62

This is actually the origin of the above case that fails in FF.

Matt Kruse

VK

unread,
Nov 26, 2007, 4:37:13 PM11/26/07
to
On Nov 27, 12:21 am, Matt Kruse <m...@mattkruse.com> wrote:
> Unfortunately, in Firefox:
>
> var o = document.createElement("object");
> alert(typeof o); // "function"
> o(); // ERROR

For such primitive case one may use isPrototypeOf method:

var x = document.createElement('object');
var y = new Function;
window.alert(Function.prototype.isPrototypeOf(x)); // false
window.alert(Function.prototype.isPrototypeOf(y)); // true

Again the prototype chain might be screwed up completely, on Gecko
including the direct hack of __proto property, so se my other post
about what one may consider as "possible" or "not possible".


Thomas 'PointedEars' Lahn

unread,
Nov 26, 2007, 4:39:32 PM11/26/07
to
VK wrote:
> On Nov 26, 9:41 pm, Matt Kruse <m...@mattkruse.com> wrote:
>> I know the argument can be made that this is bad design to not know
>> whether or not you're passing in something that can be called as a
>> function. But I'm asking as a purely technical question, whether or
>> not it's possible.
>
> In "standard" clj terms ("it is not possible for 100% - it is not
> possible at all") it is not possible.
>
> The evident way is to use typeof:
> if (typeof something == 'function') {
> }
>
> but in IE some/many native methods of window or document are reported
> as "object" instead of "function" despite still can be used in [Call]
> context.

The most obvious and oft-recommended solution is

/**
* @author
* (C) 2003, 2004 Thomas Lahn &lt;type...@PointedEars.de&gt;
* Distributed under the GNU GPL v2.
* @partof
* http://pointedears.de/scripts/types.js
* @optional string s
* String to be determined a method type, i.e. "object"
* in IE, "function" otherwise. The type must have been
* retrieved with the `typeof' operator, thus this method
* is applicable to unknown properties while
* @link{#isMethod()} is not. Note that this method
* may also return <code>true</code> if the value of
* the <code>typeof</code> operand is <code>null</code>; to
* be sure that the operand is a method reference, you have
* to && (AND)-combine the <code>isMethodType(...)</code>
* expression with the method reference identifier.
* @return type boolean
* <code>true</code> if <code>s</code> is a method type,
* <code>false</code> otherwise.
* @see #isMethod()
*/
function isMethodType(s)
{
return /\b(function|object)\b/i.test(s);
}

and then

if (isMethodType(typeof o.property)
&& o.property)
{
... o.property(...) ...
}

which has sufficed to date.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Matt Kruse

unread,
Nov 26, 2007, 5:28:25 PM11/26/07
to
On Nov 26, 3:39 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
> The most obvious and oft-recommended solution is:

> function isMethodType(s)
> {
> return /\b(function|object)\b/i.test(s);
> }
> and then
> if (isMethodType(typeof o.property)
> && o.property)
> {
> ... o.property(...) ...
> }
> which has sufficed to date.

in IE:

function isMethodType(s) {
return /\b(function|object)\b/i.test(s);
}

function isFunction(o) {
return !!o && isMethodType(typeof o);
}
window.onload = function() {
alert(isFunction(document.body.firstChild)); // true
//document.body.firstChild() // ERROR
var a = document.createElement("a");
document.body.appendChild( a );
alert(isFunction(a)); // true
//a(); // ERROR
}

Matt Kruse

Richard Cornford

unread,
Nov 26, 2007, 6:12:09 PM11/26/07
to
Matt Kruse wrote:

> On Nov 26, 1:54 pm, Richard Cornford wrote:
>> You might reasonably say that if - typeof x - was 'function'
>> then it would be safe to call the object, and be correct in
>> all the environments that I have ever encountered.
>
> Unfortunately, in Firefox:
>
> var o = document.createElement("object");
> alert(typeof o); // "function"
> o(); // ERROR

You are making a surprisingly obvious mistake here. You are assuming that because calling a
function results in an exception being thrown then that means that the function/object is not
callable. When you think about that it is pretty obvious that such a conclusion is not valid.

In Firefox, when you call an object that is not callable the exception thrown is "o is not a
function", but the exception here is "Component is not available", so you cannot prove that the
object is not callable, only that calling it throws an exception. It could be that if and when
the "Component" (whatever that may be in this case) was available you could happily call the
function/object without an exception being thrown.

The bottom line is that an object's being callable is no guarantee that calling will be an error
free operation.

<snip>


> This is actually the origin of the above case that
> fails in FF.

So this is not your mistake, you just didn't think about it enough to see who was being fooled
here.

Richard.

Matt Kruse

unread,
Nov 26, 2007, 10:31:41 PM11/26/07
to
On Nov 26, 5:12 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> > var o = document.createElement("object");
> > alert(typeof o); // "function"
> > o(); // ERROR
> In Firefox, when you call an object that is not callable the exception thrown is "o is not a
> function", but the exception here is "Component is not available", so you cannot prove that the
> object is not callable, only that calling it throws an exception.

This gets into a pretty gray area, then, doesn't it? How could you
ever know that _any_ object that is callable will not result in an
error? Should everything be wrapped in a try/catch?

Your original statement was:


> You might reasonably say that if - typeof x - was 'function' then it would be safe to call the
> object, and be correct in all the environments that I have ever encountered.

so I was trying to demonstrate a situation where it is not in fact
"safe" to call an object with typeof=="function". If by "safe" you
mean "won't throw an error".

> The bottom line is that an object's being callable is no guarantee that calling will be an error
> free operation.

But if you extend that to the absurd, then you have no guarantee that
calling something like alert() will be an error free operation, do
you?

I think it should be safe to conclude that anything reporting itself
as typeof=="function" should be callable without throwing an error,
and in this case FF has a bug. Nevertheless, it's a bug that needs to
be worked around in any code that is trying to figure out if a given
object should be treated as a callable function.

The root cause of this mess in jQuery seems to be that the API tries
to "overload" methods to handle various types of arguments, like

func(object, object)
or
func(object, function)

so there is a "need" to figure out which type of method signature is
being called. I do tend to like this kind of "overloading" in many
cases because it results in very dense and flexible code, but given
the problems involved in truly testing whether an argument is a
callable function, I think this design decision is a flaw.

Matt Kruse

Richard Cornford

unread,
Nov 27, 2007, 4:12:42 AM11/27/07
to
Matt Kruse wrote:

> On Nov 26, 5:12 pm, Richard Cornford wrote:
>> > var o = document.createElement("object");
>> > alert(typeof o); // "function"
>> > o(); // ERROR
>> In Firefox, when you call an object that is not callable
>> the exception thrown is "o is not a function", but the
>> exception here is "Component is not available", so you
>> cannot prove that the object is not callable, only that
>> calling it throws an exception.
>
> This gets into a pretty gray area, then, doesn't it?

It suggests that there is limited use in knowing that something is callable.

> How could you ever know that _any_ object that is
> callable will not result in an error?

By knowing what it is you are calling (say knowing that - document.getElementById - is forbidden
from throwing an exception) or by testing that conditions that would result in an exception
being thrown don't apply before taking actions that may result in their being thrown.

> Should everything be wrapped in a try/catch?

Almost nothing should be wrapped in try-catch because javascript's exception handling is far too
poor to allow sensible error handling. Defensive programming to avoid runtime errors is a far
superior approach.

> Your original statement was:
>> You might reasonably say that if - typeof x - was
>> 'function' then it would be safe to call the object,
>> and be correct in all the environments that I have
>> ever encountered.
>
> so I was trying to demonstrate a situation where it is
> not in fact "safe" to call an object with
> typeof=="function".

And you did not do that.

> If by "safe" you
> mean "won't throw an error".

The act of calling the object has not been shown to throw an error. Instead the consequence of
calling; the resulting execution of code, appears to be where the exception is occurring.

>> The bottom line is that an object's being callable is no
>> guarantee that calling will be an error free operation.
>
> But if you extend that to the absurd, then you have no
> guarantee that calling something like alert() will be
> an error free operation, do you?

Fortunately browsers are rarely absurd. Remember that you started off trying to call the object
returned from - document.createElement("object") - without any reason for expecting that to have
any certain outcome at all.

> I think it should be safe to conclude that anything
> reporting itself as typeof=="function" should be
> callable without throwing an error,

Don't be ridiculous. Even programmer defined functions are allowed to throw exceptions while
they execute.

Remember that host methods may throw exceptions if they receive the wrong number or type of
arguments (that is pretty common) and knowing that something is callable will not tell you
anything about the arguments that it is expecting when it is called.

> and in this case FF has a bug.

What makes it a bug?

> Nevertheless, it's a bug that needs to be worked
> around in any code that is trying to figure out if a given
> object should be treated as a callable function.

Given that knowing something is callable is never enough to tell you that calling it will be
error free you are just describing a stupid design and then saying that the aspects of the
design that make it stupid become a problem in context.

Don't design code that attempts to call function/methods without first having a very good idea
of what those functions/method are, and what the consequences of calling them is likely to be.

> The root cause of this mess in jQuery seems to be that
> the API tries to "overload" methods to handle various
> types of arguments, like
>
> func(object, object)
> or
> func(object, function)
>
> so there is a "need" to figure out which type of
> method signature is being called.

Maybe, but we have already discovered that JQuery written by a novice who is far too arrogant to
even consider whether he has made any mistakes, let alone recognise the ones he has made. How
often have we witnessed that superficial success in the early stages of learning javascript
result in individuals acquiring a total unrealistic overconfidence in their own abilities?

> I do tend to like this kind of "overloading" in many
> cases because it results in very dense and flexible code,
> but given the problems involved in truly testing whether
> an argument is a callable function,

But clearly the issue is not whether the argument is callable or not. We have seen that that
information alone is not sufficient here. You certainly learn nothing about the number and type
of any possibly required arguments from that information, and that is just the start of the
ongoing problems with such a reckless strategy.

> I think this design decision is a flaw.

Absolutely, but what chance of it being fixed in this library? The fix would radically alter the
nature of the API, and so render all pre-existing code that uses the library non-updateable. It
is a pity that the people who make these things do not spend some time learning the browser
scripting issues before they start because then they may be able to avoid tying hundreds of
other people's projects to their ill thought out code.

Richard.

Thomas 'PointedEars' Lahn

unread,
Dec 1, 2007, 6:43:35 AM12/1/07
to

Firstly, one problem problem with your implementation is that it evaluates
the value before determining its type, where mine does it vice-versa.

Secondly, you are missing the simple fact that noone in their right mind
would try to determine if a document node would be callable.


PointedEars

Matt Kruse

unread,
Dec 1, 2007, 9:28:27 AM12/1/07
to
On Dec 1, 5:43 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Secondly, you are missing the simple fact that noone in their right mind
> would try to determine if a document node would be callable.

I must have missed the note in your documentation that says what you
can and can't pass to get accurate results. So you have to know what
something is ahead of time, before determining if it is callable?

Imagine a function that can take any type of input, and does different
things depending on what is passed in. You might need to determine if
the user has passed in a callable object or a document node.

It's already been said that there is probably no fool-proof way to
determine if something is truly callable. Your "solution" which has
limitations and gets it wrong in some cases is really no improvement
over countless other attempts.

Matt Kruse

Thomas 'PointedEars' Lahn

unread,
Dec 1, 2007, 10:04:37 AM12/1/07
to
Matt Kruse wrote:
> On Dec 1, 5:43 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> wrote:
>> Secondly, you are missing the simple fact that noone in their right mind
>> would try to determine if a document node would be callable.
>
> I must have missed the note in your documentation that says what you
> can and can't pass to get accurate results. So you have to know what
> something is ahead of time, before determining if it is callable?

That's ridiculous. Do you even recognize what you are saying?

> Imagine a function that can take any type of input, and does different
> things depending on what is passed in. You might need to determine if
> the user has passed in a callable object or a document node.

That is where you are misguided. Such a function simply is not required
in reasonable programming.

Matt Kruse

unread,
Dec 1, 2007, 10:13:16 AM12/1/07
to
On Dec 1, 9:04 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> > Imagine a function that can take any type of input, and does different
> > things depending on what is passed in. You might need to determine if
> > the user has passed in a callable object or a document node.
> That is where you are misguided. Such a function simply is not required
> in reasonable programming.

That's a whole different point. One I made a while ago, in fact,
saying that such a requirement in an API may be bad design. Then
again, it may not. A function that takes a single argument and acts
"appropriately" no matter what kind of argument is passed to it is
extremely useful. Otherwise you'll end up with myfunc_string(a),
myfunc_number(a), myfunc_function(a), etc. That's a mess.

But that's irrelevant.

I was asking about whether it was really possible to determine if
something is callable in all cases, or if it was possible to get
pretty close. Your "solution" comes nowhere close.

Criticism has been made of the attempts by libraries like jQuery and
Dojo, but when you consider different cases where browsers return
questionable results from typeof, etc, then you can understand why
they use "weird" logic to try to really determine the best guess.

Matt Kruse

VK

unread,
Dec 1, 2007, 10:24:56 AM12/1/07
to
On Dec 1, 5:28 pm, Matt Kruse <m...@mattkruse.com> wrote:
> It's already been said that there is probably no fool-proof way to
> determine if something is truly callable.

Coming to you original request, the task was to make the program aware
of the current Firefox bug where OBJECT HTML element reported as
typeof "function" instead of "object". A truly right sequence would
actually be:
1) Report the bug at bugzilla.mozilla.org with the minimum demo case
like:
<script>
var foo = document.createElement('P');
var bar = document.createElement('OBJECT');
window.alert(typeof foo); // 'object'
window.alert(typeof bar); // 'function'
</script>
Such evident bugs caused by a simple typo in the name table are
usually being fixed in the next minor update.

2) Having referenced this bug in your port you would ask how to
overcome this bug for the time being in case of dealing with a 3rd
party library sending arguments to your methods.

In this case it could be suggested to relay for the next 2-3 months on
toString method of DOM Elements which is lucky not broken:

var foo = document.createElement('P');
var bar = document.createElement('OBJECT');
window.alert(typeof foo); // 'object'
window.alert(typeof bar); // 'function'
// but:
window.alert(foo); // 'object HTMLParagraphElement'
window.alert(bar); // 'object HTMLObjectElement'

On a wider run we have two types of bugs of this kind currently
exposed by some browsers:
1) non-callable objects reported by typeof as "function"
2) callable objects reported by typeof as "object"

One bug of this kind is just mentioned. One bug of the second type
would be say window.alert(typeof document.createElement); that gives
"object" for IE

First we are leaving out philosophical approaches of "covering each
and every possible bug on any browser on any platform in the past,
present and future".

Having made this - very painful for some but necessary step - on of
suggested workarounds could be to check toString() return values.
For the situation 1), exposed by Firefox, check if toString return
value contains "object HTML" substring.
For the situation 2), exposed by IE, check if toString return value
contains "function". On IE all DOM methods uniformly reported by
toString as
"function methodName() {
[native code]
}"
while non-callable DOM objects reported as "[object]".

So again: there is not any problem if someone is doing a real
practical task. If the subject is again about the "futility to try to
make a reliable program" and stuff the clj is not the best place for
it IMO. comp.programming is mush better for that.

VK

unread,
Dec 1, 2007, 10:51:11 AM12/1/07
to
On Dec 1, 6:24 pm, VK <schools_r...@yahoo.com> wrote:
> 1) Report the bug at bugzilla.mozilla.org

No need to do it:

https://bugzilla.mozilla.org/show_bug.cgi?id=296858
and
https://bugzilla.mozilla.org/show_bug.cgi?id=346789
as dups of
https://bugzilla.mozilla.org/show_bug.cgi?id=268945
"Applet tag returns function instead of object with typeof JavaScript
method".

Still a reference to bug ID would be helpful so side readers could
know if one looking for a particular bug workaround or with some
universal JS/DOM feature.

VK

unread,
Dec 1, 2007, 11:44:47 AM12/1/07
to
On Dec 1, 6:24 pm, VK <schools_r...@yahoo.com> wrote:
> So again: there is not any problem if someone is doing a real
> practical task.

In the particular, in those rare cases when really needed - without
any claims that it is the absolutely best out of possible solutions:

function $typeof(obj) {
/* Firefox APPLET and OBJECT typeof bug
* workaround.
*/
if ('tagName' in obj) {
return 'object';
}
/* IE DOM methods bug workaround.
* IE DOM Elements do not support
* explicit toString method call
* ('no such property' error)
* so using implicit call instead.
*/
else if ( ('ActiveXObject' in window) &&
((''+obj).indexOf('function')!=-1) ) {
return 'function';
}
else {
return typeof obj;
}
}

Anyone is welcome to add as many extra checks as desired: the presence
of argument, of argument not being a primitive etc. A very important
thing to remember is that there is nothing for free in this world:
more paranoiac your method becomes - more protected it is from
possible misuse; but at the same time it gets slower for the normal
documented usage of your program. So for a real (not theoretical)
programming the task is not to put as many possible checks as one can
think of. The real task is to find the border line of a reasonable
misuse protection and after that let program die.

"If someone really wants to make the program die - so let him".

Message has been deleted

Matt Kruse

unread,
Dec 1, 2007, 1:03:11 PM12/1/07
to
> else if ( ('ActiveXObject' in window) &&

This is and always has been a terrible way to infer anything.
Use conditional compilation instead, which will only run in the
JScript engine where the "problems" exist.

> ((''+obj).indexOf('function')!=-1) ) {
> return 'function';
> }

This is way to broad. An object like
{ description:'This lets you test for a function'}
would be labeled a 'function' by your $typeof function.

> The real task is to find the border line of a reasonable
> misuse protection and after that let program die.

The real task is to figure out exactly how you want such a function to
operate and on which browsers. It is possible to approach a general
solution that works in all cases, but never reach it. By identifying
browser quirks with respect to host objects and accounting for them
you can cover most cases, which may be good enough. But some such
fixes need to be browser-specific and the code required to implement
it becomes complex.

I've got some improved code that I've been working on that uses
conditional compilation and the "russian doll" technique to unroll
itself to the most efficient function after a few tests have been run
the first time. So far I think it comes the closest to being accurate
of any approach I've seen so far. I'll post it for critique when I get
it done.

Matt Kruse

VK

unread,
Dec 1, 2007, 1:31:44 PM12/1/07
to
On Dec 1, 9:03 pm, Matt Kruse <m...@mattkruse.com> wrote:
> > else if ( ('ActiveXObject' in window) &&
>
> This is and always has been a terrible way to infer anything.
> Use conditional compilation instead, which will only run in the
> JScript engine where the "problems" exist.

Unless someone will implement a browser with conditional compilation
and IE spoofing. :-))

Taking into account the OTC deal of browser producers ("spoof whatever
you need but ActiveXObject") this property check is very reliable as
well - again on condition that someone is trying to use your program
and not to get a runtime error. There is no protection for a
determined user of the latter kind - but he/she never was a subject of
my preoccupations. Within the same OTC deal for IE/Gecko branches it
is pretty secure to:
if ('ActiveXObject' in window) {
// IE branch
}
else if ('GeckoActiveXObject' in window) {
// Gecko block
}
else if ('opera' in window) {
// Opera block
}
else {
// some lesser-minor UA
}

Again: no offence of any kind to the conditional compilation instead.

> > ((''+obj).indexOf('function')!=-1) ) {
> > return 'function';
> > }
>
> This is way to broad. An object like
> { description:'This lets you test for a function'}
> would be labeled a 'function' by your $typeof function.

Are you sure about it? ;-) Do not mix an object property value with
toString of the object itself.

VK

unread,
Dec 1, 2007, 1:51:23 PM12/1/07
to
On Dec 1, 9:31 pm, VK <schools_r...@yahoo.com> wrote:
> > > ((''+obj).indexOf('function')!=-1) ) {
> > > return 'function';
> > > }
>
> > This is way to broad. An object like
> > { description:'This lets you test for a function'}
> > would be labeled a 'function' by your $typeof function.
>
> Are you sure about it? ;-) Do not mix an object property value with
> toString of the object itself.

What is bad in this block is that it will make unnecessary checks for
JScript objects where typeof always works just fine. Because in IE DOM
model DOM objects have nothing to do with JScript objects the
suggested optimization could be:

else if (('ActiveXObject' in window) &&
(!Object.prototype.isPrototypeOf(obj)) &&
((''+obj).indexOf('function')!=-1)) {
return 'function';
}

Matt Kruse

unread,
Dec 1, 2007, 4:21:16 PM12/1/07
to
On Dec 1, 12:03 pm, Matt Kruse <m...@mattkruse.com> wrote:
> I've got some improved code that I've been working on that uses
> conditional compilation and the "russian doll" technique to unroll
> itself to the most efficient function after a few tests have been run
> the first time.

Okay, my syntax has changed a bit, but see my "improved" function
below. It passes all the jQuery test cases and the additional test
cases from the article on "DHTML Kitchen". It's a little bit weird and
could surely stand to be improved, so go ahead and critique all you
want! I've tested it in IE6, FF2, and Safari3 on Windows. That's all I
have access to at the moment.

var isFunction = (function() {
/*@cc_on
// IE reports some element node methods as objects, but when
converted to string
// they always have the text 'function' and '[native code]' in them
when they
// are actually functions.
// Anything reported as typeof=='function' is always a function
(AFAIK).
return function(o) {
if (typeof o=='function') { return true; }
if (typeof o=='object') {
if (/function/.test(o) && /\[native code\]/.test(o)) {
return true;
}
}
return false;
}
@*/

// For other browsers, we're going to build a function as a string
and only add the
// tests that are actually required by the browser to overcome bugs/
quirks
var func = "";
func += "var o2;\nif(typeof o !='function') { return false; }\n";

// Check for Firefox because it says
document.createElement("object")=='function'
// If the object has a nodeName property (looks like an element
node), then try to create
// a new element of the same type to see if it is typeof=='function'.
If so, we can
// conclude that the original object was an element, not a real
function
if (document.createElement && typeof
document.createElement('object')=='function') {
func += "if (o.nodeName && document.createElement && (o2 =
document.createElement(o.nodeName)) && typeof o2=='function') { return
false; }\n";
}
// Firefox reports RegExp objects as 'function'
if (typeof new RegExp=='function') {
func += "if (typeof o.exec=='function' && /^\\/.*\\/\\w*$/.test(o))
{ return false; }\n";
}

// Safari reports NodeList objects as 'function'
if (document.images && typeof document.images=='function' && /\
[object HTMLCollection\]/.test(document.images) ) {
func += "if (/\[object/.test(o)) { return false; }\n";
}

// The default case - if it says it's a function, trust it
func += "return true;\n";

return Function("o",func);
})();

Matt Kruse

VK

unread,
Dec 2, 2007, 4:14:56 AM12/2/07
to
On Dec 2, 12:21 am, Matt Kruse <m...@mattkruse.com> wrote:
> Okay, my syntax has changed a bit, but see my "improved" function
> below. It passes all the jQuery test cases and the additional test
> cases from the article on "DHTML Kitchen". It's a little bit weird and
> could surely stand to be improved, so go ahead and critique all you
> want! I've tested it in IE6, FF2, and Safari3 on Windows. That's all I
> have access to at the moment.

Feel free to disregard any of my comments. In the original code my
comments marked as // # (with number sign)
Besides the commented changes I just extra broke some long strings
exclusively for the Usenet post to try to avoid code-smashing wraps.

var isFunction = (function() {

// # conditional compilation needs a condition;
// # also once turned on it is highly suggested
// # to turn it off by the end.
// #
// # JScript pragma commands structure adjusted.

/*@cc_on @*/

/*@if (@_jscript)

// IE reports some element node methods as objects,

// but when converted to string they always have
// the text 'function' and '[native code]' in them
// when they are actually functions.


// Anything reported as typeof=='function' is always

// a function (AFAIK).

return function(o) {
if (typeof o=='function') {
return true;
}

// # if - else if - else, no pending 'if'
// # Not an error but if it's for public
// # attention then let's be accurate ;-)

else if (typeof o=='object') {

// # On IE for DOM elements implicit toString call
// # returns either "function ..." or "[object]"
// # or "unknown" (for some external ActiveX controls):
// # so the 2nd check adds absolutely nothing to the job:
// # /\[native code\]/.test(o) removed
// #
// # At the same time for JScript objects toString
// # method is often overloaded, say to return empty
// # string to prevent source dump.
// # Because the problem affects only DOM elements
// # and because DOM elements are strictly separate
// # from JScript objects in IE then to secure ourselves
// # from overloaded toString and from unnecessary checks:

return Object.prototype.isPrototypeOf(o) ?
typeof o : /^function/.test(o);
}
}

@else @*/

// For other browsers, we're going to build a function

// as a string and only add the tests that are actually
// required by the browser to overcome bugs/quirks.

// # nodeName block further down is optimized to
// # avoid intermediary var assignment: o2 declaration
// # removed.

var func = "if(typeof o !='function') { return false; }\n";

// Check for Firefox because it says

// document.createElement("object")=='function'


// If the object has a nodeName property

// (looks like an element node), then try to create


// a new element of the same type to see if it is typeof=='function'.

// If so, we can conclude that the original object was an element,
// not a real function
// #
// # The bug is exposed for APPLET and OBJECT to be exact.
// #
// # As you check for document.createElement method on
// # method construction then there is no need to re-check
// # it on each method call: nobody will steal it from you :-)

if (document.createElement &&
typeof document.createElement('object')=='function') {

func+= "if (o.nodeName && " +
"typeof document.createElement(o.nodeName)=='function')" +
"{ return false; }\n";
}

// Firefox reports RegExp objects as 'function'
if (typeof new RegExp=='function') {

// * If you want to know about RegExp instances
// * then check for RegExp instances! JavaScript
// * maybe not C++ but at the same time not some
// * GBASIC to spit on OOP completely ;-)
func += "if (RegExp.prototype.isPrototypeOf(o))"+
"{ return false; }\n";
}

// Safari reports NodeList objects as 'function'

// # document.images or document.forms are not NodeList
// # but HTMLCollection. NodeList would be from say
// # document.getElementsByTagName(tname). The principal
// # differences are read-only, no update on iteration
// # for HTMLCollection.
// # Is document.getElementsByTagName('IMG') also
// # reported as "function" by Safari?


if (document.images && typeof document.images=='function' &&
/\[object HTMLCollection\]/.test(document.images) ) {
func += "if (/\[object/.test(o)) { return false; }\n";
}

// The default case - if it says it's a function,

// trust it


func += "return true;\n";

return Function("o",func);

// # Switch pragma reader off:
/*@end @*/
})();

VK

unread,
Dec 2, 2007, 7:39:17 AM12/2/07
to
On Dec 2, 12:14 pm, VK <schools_r...@yahoo.com> wrote:
> // # Because the problem affects only DOM elements
> // # and because DOM elements are strictly separate
> // # from JScript objects in IE then to secure ourselves
> // # from overloaded toString and from unnecessary checks:
>
> return Object.prototype.isPrototypeOf(o) ?
> typeof o : /^function/.test(o);
> }
> }

Oops... The function always returns true/false, not typeof results:

return Object.prototype.isPrototypeOf(o) ?
(typeof o == 'function') : /^function/.test(o);

Matt Kruse

unread,
Dec 2, 2007, 4:56:26 PM12/2/07
to
On Dec 2, 3:14 am, VK <schools_r...@yahoo.com> wrote:
> // # conditional compilation needs a condition;

No it doesn't. It will run in the JScript engine, and won't elsewhere.
No need for a condition.

> // # if - else if - else, no pending 'if'
> // # Not an error but if it's for public
> // # attention then let's be accurate ;-)
> else if (typeof o=='object') {

No need for else if the first block returns early from the function.

> // # On IE for DOM elements implicit toString call
> // # returns either "function ..." or "[object]"
> // # or "unknown" (for some external ActiveX controls):
> // # so the 2nd check adds absolutely nothing to the job:
> // # /\[native code\]/.test(o) removed

Actually, it is needed. In your version,
isFunction( ["function"] )
would return true.

> // # nodeName block further down is optimized to
> // # avoid intermediary var assignment: o2 declaration
> // # removed.

True, that was leftover from previous code and unnecessary.

> // # As you check for document.createElement method on
> // # method construction then there is no need to re-check
> // # it on each method call: nobody will steal it from you :-)

Oops, good catch on that typo.

> // * If you want to know about RegExp instances
> // * then check for RegExp instances!

I suppose. I've never used isPrototypeOf, so I'd have to make sure
that it's a good choice to use it in this case.

> // Safari reports NodeList objects as 'function'
> // # document.images or document.forms are not NodeList
> // # but HTMLCollection.

Yes. I originally coded it with something that was a NodeList, and
that's when I wrote the comment.

> // # Switch pragma reader off:
> /*@end @*/})();

Not really necessary.

Thanks for a few useful comments.

Matt Kruse

Matt Kruse

unread,
Dec 2, 2007, 11:21:31 PM12/2/07
to
On Dec 2, 3:14 am, VK <schools_r...@yahoo.com> wrote:
> return Object.prototype.isPrototypeOf(o) ?
> ...

> func += "if (RegExp.prototype.isPrototypeOf(o))"+

Fails across windows, yes?

Matt Kruse

dhtmlk...@gmail.com

unread,
Dec 3, 2007, 1:18:39 AM12/3/07
to
On Dec 1, 7:24 am, VK <schools_r...@yahoo.com> wrote:
> On Dec 1, 5:28 pm, Matt Kruse <m...@mattkruse.com> wrote:
>
I'm thinking the answer is to avoid having strong reliance on typeof
in checking arguments to functions, and then making further
assumptions based on the return of typeof. This is the typical fake
overloading approach -- switch on arguments[0], et c.

The reason the libraries get themselves in this situation is that
they're using this approach.

It's the fake overloading approach that is the problem. It is a
problem because it assumes things based on the return of typeof.

And so the best approach is to avoid using fake method overloading
with variant types/variant behavior per method. Instead, I think a
better approach is to use explicit methods.

That's my opinion,.

Richard Cornford

unread,
Dec 6, 2007, 1:57:12 PM12/6/07
to
Matt Kruse wrote:

> On Dec 1, 12:03 pm, Matt Kruse wrote:
>> I've got some improved code that I've been working on
>> that uses conditional compilation and the "russian doll"
>> technique to unroll itself to the most efficient function
>> after a few tests have been run the first time.
>
> Okay, my syntax has changed a bit, but see my "improved"
> function below. It passes all the jQuery test cases and
> the additional test cases from the article on "DHTML
> Kitchen". It's a little bit weird and could surely stand
> to be improved, so go ahead and critique all you want!
> I've tested it in IE6, FF2, and Safari3 on Windows.
> That's all I have access to at the moment.
>
> var isFunction = (function() {

If there is one thing that is clear from this discussion it is that this
is a very wrong name for this function to have. This function is
attempting to make a discrimination, but that discrimination is not
between objects that are functions and objects that are not functions.
If that was the discrimination that was to be made it would then be
essential to pin down what it was precisely that qualified an object as
a function (and it may be necessary to accept that such a discrimination
was an impossibility if the objects were to include host objects).

In practice JQuery has designed in an issue of discriminating that is
very different form identifying objects that are or are not functions.
To date the precise nature of this requirement have never been stated
here, and without that it designing an appropriate test to make the
discrimination is impractical.

> /*@cc_on
> // IE reports some element node methods as objects,

Windows IE (but not Mac IE) report element node methods as typeof ==
'object'. In javascript functions/methods are objects.

> but when converted to string
> // they always have the text 'function' and '[native code]'
> in them when they
> // are actually functions.
> // Anything reported as typeof=='function' is always a function
> (AFAIK).
> return function(o) {
> if (typeof o=='function') { return true; }
> if (typeof o=='object') {
> if (/function/.test(o) && /\[native code\]/.test(o)) {
> return true;
> }
> }
> return false;
> }
> @*/
>
> // For other browsers, we're going to build a function as
> a string and only add the
> // tests that are actually required by the browser to
> overcome bugs/ quirks

You have not yet identified any bugs here.

> var func = "";
> func += "var o2;\nif(typeof o !='function') { return false; }\n";
>
> // Check for Firefox because it says
> document.createElement("object")=='function'

And as the object in question appears to be callable that is a
reasonable thing for Firefox to be saying.

> // If the object has a nodeName property (looks like
> an element node), then try to create
> // a new element of the same type to see if it is
> typeof=='function'. If so, we can
> // conclude that the original object was an element,
> not a real function

You may be able to conclude that the original object was an element
(which is an object (any object) implementing the Element interface) but
there is no sense is saying that it was "not a real function", because
functions are objects, may implement the Element interface, and your
example of this case certainly looked callable.

> if (document.createElement && typeof
> document.createElement('object')=='function') {
> func += "if (o.nodeName && document.createElement && (o2 =
> document.createElement(o.nodeName)) && typeof o2=='function') { return
> false; }\n";
> }
> // Firefox reports RegExp objects as 'function'
> if (typeof new RegExp=='function') {
> func += "if (typeof o.exec=='function' && /^\\/.*\\/\\w*$/.test(o))
> { return false; }\n";
> }
>
> // Safari reports NodeList objects as 'function'

As do (at minimum) Mac IE, Konqueror, Opera versions at least up to 8,
Ice browser and some others. This is in fact so common that you really
have had to have your head buried in the sand for many years not to have
anticipated that this would be an issue.

> if (document.images && typeof document.images=='function' && /\
> [object HTMLCollection\]/.test(document.images) ) {

^^^^^^^^^^^^^^^^^^^^^
There is nothing that specifies the return value from a nodeList's -
toString - method so this test will be no better than it has been
observed to be. Leaving all the other browsers that have functions as
the object that implements the NodeList interface likely to be fooling
this code.

> func += "if (/\[object/.test(o)) { return false; }\n";
> }
>
> // The default case - if it says it's a function, trust it
> func += "return true;\n";
>
> return Function("o",func);
> })();

It cannot possibly be the case that the JQuery functions that need this
discrimination have been written with the expectation that thy can be
passed anything at all (that would be insane). So there must be some
specific set of possible arguments to be tested, and some particular
discrimination to be made between them. It seems to me that it may be
more productive to forget about this 'isFunction' discrimination and
instead set about pinning down what it is that the JQuery function(s)
really needs to know about its arguments, as there may be far simpler
'duck typing' tests that could be applied in context

Richard.

VK

unread,
Dec 7, 2007, 11:43:12 AM12/7/07
to

Sorry for delay, I had to be out of town for a while..

One cannot use constructors from one window/frame for object
instantiations in the current window/frame: that leads to one of the
most obscure and random runtime errors in JScript: "Can't execute code
from a freed script". It may work for iframe, mostly fails for
frameset and window. Some maniacs still trying to hack it by using
call wrappers like
var foo = OtherWindowReference.FunctionName();
and in OtherWindow:
FunctionName() {
return new MyObject();
}

"freed script" error still comes sooner or later but even in more
random and obscure way. So yes, such misuse can be met in some
libraries, I saw it myself - but we decided(?) that we don't consider
neither developers devoted to make a non-working code, nor end-users
devoted to crash the program. From this point of view any arguments
about cross-Global OOP should be dismissed; as well as say a
possibility to use constructors and then patch __proto__ property
(where available).

VK

unread,
Dec 7, 2007, 12:12:40 PM12/7/07
to
On Dec 3, 12:56 am, Matt Kruse <m...@mattkruse.com> wrote:
> On Dec 2, 3:14 am, VK <schools_r...@yahoo.com> wrote:
>
> > // # conditional compilation needs a condition;
>
> No it doesn't. It will run in the JScript engine,
> and won't elsewhere. No need for a condition.

You are wrong: the minimum required syntax for pragma reader is:
/*@cc_on @ */
/*@if (some_condition)
// some source code
@else @*/
// some source code
/*@end @*/

The code you have originally posted simply leads to the "syntax error"
on IE. Without closing @end pragma it is still syntax error but more
informative: about missing end pragma. Sometimes it is not needed to
build any complex condition and the question only is "IE or not IE".
In such case one normally uses @if (@_jscript) check - it always
returns true for IE. So then really minimalistic conditional
compilation syntax is:

/*@cc_on @*/
/*@if (@_jscript)
// some source code
@else @*/
// some source code
/*@end @*/

One of defaults of the current implementation is that there is no
explicit way to write fall-through branching: so "include this if
(true) but also include the rest of source". As a workaround one
normally uses the above block with empty "else" branch:

/*@cc_on @*/
/*@if (@_jscript)
// some source code
@else @*/
// NOP
/*@end @*/
// the rest of code

Pre-processor has to be turned off as soon as not needed anymore.
Don't forget that it is not a parser on this stage - it is pre-
processor preparing text source code to be sent to parser. Don't make
him to keep going through the whole 10Kb - 600Kb js file in search of
more pragma commands. Inefficient first, dangerous second - in case of
same obfuscated source on the go.

> > // # if - else if - else, no pending 'if'
> > // # Not an error but if it's for public
> > // # attention then let's be accurate ;-)
> > else if (typeof o=='object') {
>
> No need for else if the first block returns early from the function.

OK

> > // # On IE for DOM elements implicit toString call
> > // # returns either "function ..." or "[object]"
> > // # or "unknown" (for some external ActiveX controls):
> > // # so the 2nd check adds absolutely nothing to the job:
> > // # /\[native code\]/.test(o) removed

> Actually, it is needed. In your version,
> isFunction( ["function"] )
> would return true.

On what browser? Again, you seem mixing property values of objects and
toString return value of object itself: they have nothing to do with
each other unless overloaded toString.

> > // * If you want to know about RegExp instances
> > // * then check for RegExp instances!
>
> I suppose. I've never used isPrototypeOf, so I'd have to make sure
> that it's a good choice to use it in this case.

You are not making a startup stage feature sniffing: you are making a
method for using runtime, possibly with hundreds and more calls at a
short period of time. In such case the proportion "more checks / more
speed" has to be shifted to "more speed" especially when the language
provides legal tools for it. IMHO.

> > // # Switch pragma reader off:
> > /*@end @*/})();
>
> Not really necessary.

See the top of my post.
/*@end @*/

0 new messages