Thomas 'PointedEars' Lahn wrote:
RobG wrote:
Randy Webb wrote:
[...]The second half of that if test seems to be superfluous and not needed.
Again, this could not be farther from the truth.
I'm sure Randy appreciated being told your view again.
[...]Shouldn't the 'typeof' operator be inside isMethodType?
No, it should not.
[...] And if `document' is not defined, a ReferenceError exception would be
thrown. I have designed that method (included in types.js) as a general
solution for the [[Call]] problem. It is as it is for a reason, you know.
Hence why I was asking, you know.
But it seems pretty pointless anyway, isMethodType will return true for
any non-null object.
Works as designed.
Without being given the original design, it is difficult for anyone else
to determine that. And without knowing precisely what it is designed to
do (or not), I am uncertain as to its suitability to various situations.
Hence the questions...
The usefulness of the 'function' test is completely subverted by the -
|| object - bit.
It is not.
Something like isMethodType is only seems relevant in a situation where
you are contributing to shared libraries and you don't know what anyone
else is doing.
No, it is relevant for _all_ feature tests. Only for DOM feature tests
you will have to add the additional type-converting test if you want to
support IE.
But a fundamental principle in such situations is usually to not overwrite
native or DOM standard methods - so given the weakness of the test, what's
the point?
The point is that you can determine reliably enough if something can be
called or not.
'reliably enough' - it is the extent of that reliability that I'd like
to understand clearly. As far as I can tell, all browsers work OK when
dealing with native JavaScript objects when test as follows:
alert( typeof Math.floor ) // shows 'function'
It's when DOM objects are involved that some brosers (e.g. IE) lose the
plot. When allowances are made for these browsers, the tests are weakened.
For example, testing whether typeof document.getElementById returns
'function' seems pretty definitive, but just testing that it's an object
and not null seems a bit soft.
That is not to say that therefore there shouldn't be any testing at all,
only that if the test is weak, can a methodology be employed that
removes the need for such tests and provides the same level of
reliability? Or a better test be devised?
Another aspect is how to determine an appropriate test for the platform
the code is running on. What feature test will tell you if typeof
function is supported for all objects?
For example, in Gecko you can look at a DOM object's constructor:
var x = document.getElementById;
if ( Function == x.constructor ) // returns true
but in IE x.constructor is undefined - which seems to hold true for all
DOM objects in IE. But IE does have a constructor property for native
JavaScript objects, why not with DOM objects and methods? (that's a
rhetorical question... :-) ).
An idea is to use toString(). IE seems to have 'undetectable' support
for toString with DOM objects, you can't call it explicitly:
e.g.
var x = document.getElementById;
alert( x ) // shows function getElementById () {...}
which looks like the result of x.toString(), but
alert( x.toString() ) // shows undefined
alert( typeof x.toString ) // shows undefined
What the...?
Can it be made more robust?
There is already isMethod() which can take a string argument and uses eval()
then (which appears to me to be the only way to avoid early evaluation),
but it breaks for null base objects. I have been working on it to handle
that, too, for some time now.
This one?
function isMethod(o)
{
if (typeof o == "string")
{
o = eval(o);
}
var t;
return ((t = typeof o) == "function" || t == "object" && o);
}
Have you considered two functions, one for native JavaScript objects and
one for DOM? e.g.:
function testMethodNative (o)
{
return ('function' == typeof o);
}
or
function testMethodNative (o)
{
return (Function == o.constructor);
}
Both seem to work fine with native objects like Math.floor, Array.join
and String.split. The following can be used to test DOM objects:
function testMethodDOM (o)
{
if ('function' == typeof document.write){
// Supports typeof function for DOM objects
return ('function' == typeof o);
} else {
// Weaker test for others
return ('object' == typeof o && null != o);
}
}
Or maybe they can be combined, similar to the typical test for
document.getElementById/document.all.
OK, testing document.write is not much better than the olde worlde
assumption that support for document.all means IE, but 'it works'. Is
it any less robust than isMethod or isMethodType? Any UA that doesn't
support document.write is likely not of much use anyway (the use of
document.write is not restricted to visual UAs and should be implemented
by any UA that supports scripting at all).
At least this way users of browsers with decent support for DOM objects
get the added protection of better feature testing, they aren't
penalised by weaker tests that allow for other browsers. This seems to
fit with the principle of graceful degradation.
Maybe a toString test can be included too (allowing for IE's
non-detectability/non-call-ability for toString with DOM objects).
function isMethod(o)
{
return /function /.test(o);
}
Here a better test would be:
return /^function /.test(o);
but IE barfs on that.
--
Rob