From: Garrett Smith on
On 2010-06-28 04:16 AM, Thomas 'PointedEars' Lahn wrote:
> RobG wrote:
>
>> The code in the article has a $() function that simply calls
>> document.getElementById() and is used precisely once. So to save
>> typing 22 characters, the author wrote a function of 53 characters
>> and spaces (plus a bunch more for the comment). Consider using
>> instead:
>>
>> var $ = document.getElementById;
>>
>> within the scope it is required. No global "$", no extra function
>> call, far fewer characters to transmit and exactly (more or less) the
>> same functionality.
>
> It does not work as you suggest because the calling object would not be that
> referred to by `document' anymore, but the Global Object. As a result, at
> least MSHTML would throw an exception. I had to observe that when writing
> JSX:dhtml.js years ago and I presume it still holds true. So a wrapper is
> required if you want an alias for this, but it should have a better, self-
> descriptive identifier (like `dom.getEBI' etc. in JSX:dhtml.js). Since then
> this method included also feature testing for the MSHTML 4 and NS 4 DOMs,
> but it would appear that these can either be safely discarded in the near
> future or moved to compatibility libraries.
>
I see your case, but I have a few disagreements.

Calling a host method with a different base object won't work in most
browsers. A function call gets its `this` value from that base object.
And for browsers that implement `getElementById` as a function and that
function needs to resolve a thisArg to the document to be searched, then
yes, the global object will be used and an error, either NativeError or
possibly TypeError would probably result.

However it *will* work in most IE versions. This is old news, appearing
in an old post of erik's weblog: "appendChild is not a function" and
restated as recently as two weeks ago wherein it was mentioned that MSIE
host methods tend to retain a reference to the base object.

var meth = document.getElementById;
meth("banner"); // Works in IE.

(Mentioned in "Need help with setTimeout"
<news:hvlt7e$h3e$1(a)news.eternal-september.org>)

MSIE host methods are not really functions although they do appear to
implement [[Call]]. This can be tested indirectly using
Function.prototype.call.call, as in:

var meth = document.getElementById;
Function.prototype.call.call(meth, document, "banner")

Exploring host methods further, I see IE9b has host methods appear to be
more like functions in that they have callable properties "call" and
"apply" that are not functions.

javascript: alert(typeof document.getElementById.call)

Though not all:
javascript: alert(typeof alert.call)

And still errors:
javascript: alert(typeof alert.blah = 1);

As far as creating a shortcut for document.getElementById, I can't see
it being justified.

Typing document.getElementById is not too long. Adding an extra function
to do that means your app has one more function in memory and for what
purpose? It's essentially a useless function that saves typing but comes
at a cost of keeping one more function in memory (with a scope chain,
etc) and the overhead of calling that additional function, which isn't
so significant, nowadays, but still redundant.

The only case where I can see using a wrapper is if you need to address
bugs in versions of IE where an element whose NAME attribute matches the
value of the parameter passed to document.getElementById. However, as
was pointed out years ago (I believe Gregor Koefler, said it): How about
just don't do that?

If typing is a problem, then an IDE autocomplete can be helpful.
Intelli-J and Eclipse are both nice.

Garrett
From: Garrett Smith on
On 2010-06-28 01:05 PM, Garrett Smith wrote:
> On 2010-06-28 04:16 AM, Thomas 'PointedEars' Lahn wrote:
>> RobG wrote:
>>

[...]

> Exploring host methods further, I see IE9b has host methods appear to be
> more like functions in that they have callable properties "call" and
> "apply" that are not functions.
>
Also mentioned here:
http://perfectionkills.com/jscript-and-dom-changes-in-ie9-preview-3/

Where it is also mentioned about typeof Option.create and typeof
Image.create are "string".

Garrett
From: Stefan Weiss on
On 28/06/10 22:05, Garrett Smith wrote:
> Exploring host methods further, I see IE9b has host methods appear to be
> more like functions in that they have callable properties "call" and
> "apply" that are not functions.
>
> javascript: alert(typeof document.getElementById.call)
>
> Though not all:
> javascript: alert(typeof alert.call)
>
> And still errors:
> javascript: alert(typeof alert.blah = 1);

Is that a typo? Maybe I'm missing something here, but why shouldn't this
produce an error? The result of |typeof alert.blah| is not a valid lvalue.


--
stefan
From: Thomas 'PointedEars' Lahn on
Garrett Smith wrote:

> Thomas 'PointedEars' Lahn wrote:
>> RobG wrote:
>>> The code in the article has a $() function that simply calls
>>> document.getElementById() and is used precisely once. So to save
>>> typing 22 characters, the author wrote a function of 53 characters
>>> and spaces (plus a bunch more for the comment). Consider using
>>> instead:
>>>
>>> var $ = document.getElementById;
>>>
>>> within the scope it is required. No global "$", no extra function
>>> call, far fewer characters to transmit and exactly (more or less) the
>>> same functionality.
>>
>> It does not work as you suggest because the calling object would not be
>> that referred to by `document' anymore, but the Global Object. As a
>> result, at least MSHTML would throw an exception. I had to observe that
>> when writing JSX:dhtml.js years ago and I presume it still holds true.
>> So a wrapper is required if you want an alias for this, but it should
>> have a better, self-descriptive identifier (like `dom.getEBI' etc. in
>> JSX:dhtml.js). Since then this method included also feature testing for
>> the MSHTML 4 and NS 4 DOMs, but it would appear that these can either be
>> safely discarded in the near future or moved to compatibility libraries.
>
> I see your case, but I have a few disagreements.

Well, you are rather prone to misconceptions.

> Calling a host method with a different base object won't work in most
> browsers.

I believe I have said that.

> [preaching to the choir]
> However it *will* work in most IE versions.

It sure did not work properly back then. Perhaps it was not MSHTML or it
was another method who was the culprit. Anyhow, it was bad advice to be
corrected.

> This is old news, appearing in an old post of erik's weblog: "appendChild
> is not a function" and

You don't mean the guy that completely botched JScript/MSHTML, do you?

> restated as recently as two weeks ago wherein it was mentioned that MSIE
> host methods tend to retain a reference to the base object.

It is an unnecessary risk to take, especially considering a proprietary,
closed source implementation; a sure sign of a script-kiddie. Why am I not
surprised to see you recommending that?

> var meth = document.getElementById;
> meth("banner"); // Works in IE.

It might work *for this method* in Wine IE 5.0 to 7.0 (I had no problems
now, but the test were only superficial and with `javascript:' in the
Address Bar). Doing that is not standard practice as far as Microsoft is
concerned, so it may very well change in one of the next versions. It is
just asking for trouble.

> just don't do that?

Exactly.


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$8300dec7(a)news.demon.co.uk>
From: Garrett Smith on
On 2010-06-28 02:10 PM, Stefan Weiss wrote:
> On 28/06/10 22:05, Garrett Smith wrote:
>> Exploring host methods further, I see IE9b has host methods appear to be
>> more like functions in that they have callable properties "call" and
>> "apply" that are not functions.
>>
>> javascript: alert(typeof document.getElementById.call)
>>
>> Though not all:
>> javascript: alert(typeof alert.call)
>>
>> And still errors:
>> javascript: alert(typeof alert.blah = 1);
>
> Is that a typo?

Yes -- that was a typo. I meant:

javascript: alert(alert.blah = 1);

That throws an error in IE9.

Maybe I'm missing something here, but why shouldn't this
> produce an error? The result of |typeof alert.blah| is not a valid lvalue.
>

It should produce an error, and for the reason you are getting at,
however it seems that "not a valid lvalue" seems a bit off as well. I
can't provide a detailed answer at this time.

Garrett