7

The following works:

    $ = document.form;
    x = $.name.value;

This doesn't:

    $ = document.getElementById;
    x = $("id").value;

Any ideas on why this doesn't work or how to make it so?

Bret Thomas
  • 297
  • 1
  • 5
  • 16
  • You might find your answer between the lines in this post/answer: http://stackoverflow.com/a/9612657/77047 – Chris Tonkinson Mar 21 '12 at 12:48
  • I'm not sure it's an exact duplicate per se, but this covers the same ground as http://stackoverflow.com/questions/6398787/javascript-shorthand-for-getelementbyid – lonesomeday Mar 21 '12 at 12:50

5 Answers5

11

The value of this depends on how you call the function.

When you call document.getElementById then getElementById gets this === document. When you copy getElementById to a different variable and then call it as $ then this === window (because window is the default variable).

This then causes it to look for the id in the window object instead of in the document object, and that fails horribly because windows aren't documents and don't have the same methods.

You need to maintain the document in the call. You can use a wrapper functions for this e.g.

function $ (id) { return document.getElementById(id); }

… but please don't use $. It is a horrible name. It has no meaning and it will confuse people who see it and think "Ah! I know jQuery!" or "Ah! I know Prototype" or etc etc.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • 1
    $ has the meaning of "id selector method", so everything is OK with that. – Bergi Mar 21 '12 at 12:52
  • 1
    @Bergi — No, it doesn't. In jQuery, for instance, it means "Get a collection of elements from a CSS selector **or** generate a collection of nodes from a fragment of HTML **or** run this function when the DOMReady event fires". – Quentin Mar 21 '12 at 12:56
  • 1
    Take a look at [these comments](http://stackoverflow.com/a/6398800/1048572). Also, jQuery is a very good example why you should not overload super-duper collection selector functions. – Bergi Mar 21 '12 at 13:02
4

The context object is different. When you get a reference of a function you're changing that context object:

var john = {
    name : "john",
    hello : function () { return "hello, I'm " + this.name }
}

var peter = { name : "peter" };

peter.hello = john.hello;

peter.hello() // "hello, I'm peter"

If you want a reference function bound to a specific context object, you have to use bind:

peter.hello = john.hello.bind(john);

peter.hello(); // "hello, I'm john"

So in your case it will be:

var $ = document.getElementById.bind(document);
ZER0
  • 22,173
  • 4
  • 45
  • 51
2

Don't know what you want to achieve, but this can be made working like this

$ = document.getElementById;
x = $.call(document, "id").value;

because getElementById works only when it is a function of document because of the scope it needs.

But I would recommend @Quentin's answer.

Diode
  • 22,062
  • 7
  • 38
  • 50
1

getElementById is a method of the HTMLDocument prototype (of which document is an instance). So, calling the function in global context you will surely get an "Wrong this Error" or something.

You may use

var $ = document.getElementById.bind(document);

but

function $(id) { return document.getElementById(id); }

is also OK and maybe better to understand.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
0

If you are trying to achieve something like that I would suggest using jQuery. Their $ notation is much more powerful than just getting an element by id.

Also, if you are using any platform that already uses the $ as a variable (ASP .Net sometimes uses this) you may have unpredictable result.

Kevin Green
  • 1,047
  • 9
  • 21