96

Is there any shorthand for the JavaScript document.getElementById? Or is there any way I can define one? It gets repetitive retyping that over and over.

Tris - archived
  • 2,437
  • 2
  • 20
  • 33
  • 6
    I don't know who downvoted them, but someone who is unfamiliar enough with Javascript that he doesn't know how to create shortcuts like this is also likely to hit problems when he tries to use it with, say, jQuery, and finds that the $ variable is not consistent. The correct answer is "No, natively Javascript does not offer a shorthand, but there are several frameworks that make selecting DOM nodes easier." – kojiro Jun 19 '11 at 13:30

21 Answers21

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

$( 'someID' )

Here I used $, but you can use any valid variable name.

var byId = function( id ) { return document.getElementById( id ); };

byId( 'someID' )
user113716
  • 299,514
  • 60
  • 431
  • 433
  • 6
    @patrick dw I like that. Especially with the wealth of valid variable names out there :) – Tris - archived Jun 18 '11 at 20:56
  • 4
    "with the wealth of valid variable names" - do you mean "at least two major JS frameworks are already using `$`, congratulations on choosing that too?" – Piskvor left the building Jun 19 '11 at 16:28
  • 51
    It makes no difference how many libraries use `$` if you never load them. – user113716 Jun 19 '11 at 17:04
  • 7
    Just for the record, I used to do `var $ = document.getElementById.bind(document)`, but `bind` isn't available in all browsers. Perhaps it's faster though, because I'm only using native methods. Just wanted to add this. – pimvdb Jun 19 '11 at 18:04
  • @pimvdb solve that problem by always including ES5 shim in your code. – Raynos Jun 20 '11 at 12:10
  • @Raynos: That's possible of course, but then it's not native and using some complicated `bind` replacement for this will actually be slower I guess. – pimvdb Jun 20 '11 at 12:22
  • 2
    @pimvdb [Benchmark](http://jsperf.com/bind-vs-dollar/2) turns out browser optimise the inlining with the JIT so `.bind` is slower. – Raynos Jun 20 '11 at 13:06
  • 1
    @patrick dw: "if you never use it" - true; this may not be true for the guy who took the code over from the guy who took the code over from the guy who took the code over from you. `$('x_hello_world').foo(); // 2007-11-20 Added to fix bar.baz()` Now what? *[cue Indiana Jones theme]* Code archeology, of course! – Piskvor left the building Jun 21 '11 at 14:46
  • 7
    @Piskvor: I never code to accommodate ignorance. Ignorance leads to broken code. Broken code leads to research. Research leads to information. Ignorance is cured. – user113716 Jun 21 '11 at 15:19
  • 1
    @patrick dw: Good point. I was worried it might lead to the Dark Side ;) – Piskvor left the building Jun 21 '11 at 15:20
  • 3
    @Piskvor No, just there are a ton of variables I could choose from for that function. – Tris - archived Jun 23 '11 at 16:06
  • I believe `var $ = document.getElementById;` should also work, just to save a couple of bytes. – GeReV Jun 27 '11 at 19:30
  • 1
    @GeReV: Actually that doesn't work. The `getElementById` method relies on being invoked from the calling context of `document`. When you invoke the method directly (via a direct reference from `$`), your calling context becomes `window` (or `undefined` in "strict mode") and breaks the function. You'd have to do `$.call(document, 'some_id')` to fix the calling context. – user113716 Jun 27 '11 at 19:34
  • ...I should clarify that I'm talking about the value of `this` in the calling context. In the context, `this` needs to reference `document`. – user113716 Jun 27 '11 at 19:41
  • Yes, you're right, I've just looked into it. Interesting, I would have expected it to work. – GeReV Jun 27 '11 at 19:56
  • GeReV, apparently it's browser specific. I don't know if your version works in any though. In Firefox the function is in the HTMLDocument prototype. So it has to know in which document you are searching for the id. – Robert Jul 13 '11 at 01:24
85

To save an extra character you could pollute the String prototype like this:

pollutePrototype(String, '绎', {
    configurable: false, // others must fail
    get: function() {
        return document.getElementById(this);
    },
    set: function(element) {
        element.id = this;
    }
});

function pollutePrototype(buildIn, name, descr) {
    var oldDescr = Object.getOwnPropertyDescriptor(buildIn.prototype, name);
    if (oldDescr && !oldDescr.configurable) {
        console.error('Unable to replace ' + buildIn.name + '.prototype.' + name + '!');
    } else {
        if (oldDescr) {
            console.warn('Replacing ' + buildIn.name + '.prototype.' + name + ' might cause unexpected behaviour.');
        }
        Object.defineProperty(buildIn.prototype, name, descr);
    }
}

It works in some browsers and you can access elements this way:

document.body.appendChild(
    'footer'.绎 = document.createElement('div')
);
'footer'.绎.textContent = 'btw nice browser :)';

I have chosen the name of the property almost randomly. If you actually wanted to use this shorthand I would suggest coming up with something easier to type.

Robert
  • 2,435
  • 23
  • 24
  • 12
    绎 (Yì) - Unravel (Simplified Chinese) – AnnanFay Jun 20 '11 at 11:32
  • 8
    You do realise that this takes a reasonable hit in efficiency. getter/setters defined on the prototype are an order of magnitude slower. – Raynos Jun 20 '11 at 13:13
  • 5
    also, that might only be one _visible_ character, but it'll take more than one byte in the file... – Alnitak Jun 20 '11 at 15:39
  • @Alnitak: oh right, I haven't thought of that. Furthermore some people (like me) don't have an 绎 key on their keyboards, so they would spend much time on copy&pasting it. But the name isn't really important. Originally I named the property 'e' (like element) but I thought this name could be claimed by some library already. – Robert Jun 20 '11 at 15:51
  • @Raynos: Yes, in my benchmark it's about three times as slow as a regular function. 0.4µs * 3 = 1.2µs – Robert Jun 20 '11 at 15:58
  • @Robert you'll be surprised how expensive going up the prototype chain and calling getter/setters are in tight loops. I've had plenty of bottlenecks with that, especially on mobile devices. – Raynos Jun 20 '11 at 16:04
  • @Raynos so _not_ polluting prototypes is the way to go? – Tris - archived Jun 21 '11 at 14:00
  • @walle1357 well it depends. It's not that bad if your polluting it with non-enumerable propeties but it has all the monkey patching problems. – Raynos Jun 21 '11 at 14:06
19

You can easily create shorthand easily yourself:

function getE(id){
   return document.getElementById(id);
}
Sarfraz
  • 355,543
  • 70
  • 511
  • 562
  • @Sarfraz Is it best to declare it as a variable or a function? Does it even matter? – user1431627 Jun 17 '13 at 08:27
  • @user1431627: If by variable you meant function expression then it does matter in terms of scope. The function posted in my answer will be available everywhere in its execution context. See: http://stackoverflow.com/questions/1013385/what-is-the-difference-between-a-function-expression-vs-declaration-in-javascrip or http://kangax.github.io/nfe/ – Sarfraz Jun 17 '13 at 19:21
  • @Sarfraz Ok, thanks :) jQuery handles this in a variable scope, right? The reason why I'm asking is because the top answer was written with a variable scope, but you wrote it as a regular function expression. – user1431627 Jun 18 '13 at 08:04
13

A quick alternative to contribute:

HTMLDocument.prototype.e = document.getElementById

Then just do:

document.e('id');

There's a catch, it doesn't work in browsers that don't let you extend prototypes (e.g. IE6).

Pablo Fernandez
  • 94,980
  • 54
  • 180
  • 225
  • 2
    @walle1357: [This article](http://perfectionkills.com/whats-wrong-with-extending-the-dom/) may interest you. – user113716 Jun 27 '11 at 20:27
  • 5
    @ThiefMaster __"Don't ever do X"__ is about the worst advice you can give. Know the alternatives, the pros and cons, and choose the best answer for every particular problem. There's no harm in extending the prototype in this case (Though I should say that other answers are a better fit, this one is left only for completion) – Pablo Fernandez Aug 22 '11 at 15:56
  • How do you know it won't break anything in some browser or in the future? – ThiefMaster Aug 22 '11 at 15:58
  • @PabloFernandez: You still don't want to extend host objects. If at least two libraries want to extend a host object with identically named properties then only the first careful library or the last careless library will succeed. – Robert Feb 17 '12 at 22:21
  • 1
    @Robert this is clearly not the best option, but it __is__ an option. You need to consider the pros and cons of every one. Remember that client side javascript libraries began with `prototype.js` which did __exactly__ this same thing. – Pablo Fernandez Feb 19 '12 at 23:00
10

id's are saved to the window.

HTML

 <div id='logo'>logo</div>

JS

logo.innerHTML;

is the same as writing:

document.getElementById( 'logo' ).innerHtml;

I don't suggest using the former method as it is not common practice.

Javid Jamae
  • 7,903
  • 4
  • 41
  • 60
im_benton
  • 2,228
  • 3
  • 18
  • 30
8

(Shorthand for not only getting element by ID, but also getting element by class :P)

I use something like

function _(s){
    if(s.charAt(0)=='#')return [document.getElementById(s.slice(1))];
    else if(s.charAt(0)=='.'){
        var b=[],a=document.getElementsByTagName("*");
        for(i=0;i<a.length;i++)if(a[i].className.split(' ').indexOf(s.slice(1))>=0)b.push(a[i]);
        return b;
    }
}

Usage : _(".test") returns all elements with class name test, and _("#blah") returns an element with id blah.

JiminP
  • 2,036
  • 19
  • 26
  • 7
    You'd better create a shortcut for [`document.querySelectorAll`](https://developer.mozilla.org/En/DOM/Document.querySelectorAll), instead of trying to emulate a part of the `querySelectorAll` method in a custom function. – Rob W Jan 14 '12 at 15:23
7
<script>
var _ = function(eId)
{
    return getElementById(eId);
}
</script>

<script>
var myDiv = _('id');
</script>
Mark Rajcok
  • 348,511
  • 112
  • 482
  • 482
genesis
  • 48,512
  • 18
  • 91
  • 118
6

There are several good answers here and several are dancing around jQuery-like syntax, but not one mentions actually using jQuery. If you're not against trying it, check out jQuery. It let's you select elements super easy like this..

By ID:

$('#elementId')

By CSS class:

$('.className')

By element type:

$('a')  // all anchors on page 
$('inputs')  // all inputs on page 
$('p a')  // all anchors within paragaphs on page 
Kon
  • 25,664
  • 11
  • 56
  • 84
  • 3
    I tried jQuery, but do i really need an entire library just for a getElementById shorthand? – Tris - archived Jun 18 '11 at 20:54
  • What is the *"jQuery-like syntax"* in the other answers? Mostly they're just plain old functions referenced by variables. There's nothing uniquely jQuery-like about that. ;o) – user113716 Jun 18 '11 at 21:04
  • 3
    @patrick dw, Right, your answer $('someID') looks nothing like a jQuery ID selector $('#someID') :) – Kon Jun 19 '11 at 11:43
5

There's none built-in.

If you don't mind polluting the global namespace, why not:

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

EDIT - I changed the function name to be something unusual, but short and not otherwise clashing with jQuery or anything else that uses a bare $ sign.

Alnitak
  • 313,276
  • 69
  • 379
  • 466
3

Yes, it gets repetitive to use the same function over and over each time with a different argument:

var myImage = document.getElementById("myImage");
var myDiv = document.getElementById("myDiv");

So a nice thing would be a function that takes all those arguments at the same time:

function getElementsByIds(/* id1, id2, id3, ... */) {
    var elements = {};
    for (var i = 0; i < arguments.length; i++) {
        elements[arguments[i]] = document.getElementById(arguments[i]);
    }
    return elements;
}

Then you would have references to all your elements stored in one object:

var el = getElementsByIds("myImage", "myDiv");
el.myImage.src = "test.gif";

But you would still have to list all those ids.

You could simplify it even more if you want all elements with ids:

function getElementsWithIds() {
    var elements = {};
    var elementList = document.querySelectorAll("[id]");
    for (var i = 0; i < elementList.length; i++) {
        elements[elementList[i].id] = elementList[i];
    }
    return elements;
}

But it would be pretty expensive to call this function if you have many elements.


So, theoretically, if you would use the with keyword you could write code like this:

with (getElementsByIds('myButton', 'myImage', 'myTextbox')) {
    myButton.onclick = function() {
        myImage.src = myTextbox.value;
    };
}

But I don't want to promote the use of with. Probably there's a better way to do it.

Robert
  • 2,435
  • 23
  • 24
2

Well, you could create a shorthand function, that's what I do.

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

and then when you wanted to get it, you just do

$('yourid')

Also, another useful trick that I found, is that if you want to get the value or innerHTML of an item ID, you can make functions like this:

function $val(el) {
    return $(el).value;
}

function $inner(el) {
    return $(el).innerHTML;
}

Hope you like it!

I actually made a kind of mini javascript library based on this whole idea. Here it is.

  • I was just looking at this question again, and found this. This is a pretty neat library if you don't want to include all of jQuery. – Tris - archived May 13 '14 at 23:34
2

I frequently use:

var byId='getElementById'
var byClass='getElementsByClass'
var byTag='getElementsByTag'


var mydiv=document[byId]('div') 
/* as document["getElementById"] === document.getElementById */

I think it's better than a external function (e.g. $() or byId()) because you can do things like this:

var link=document[byId]('list')[byClass]('li')[0][byTag]('a')[0]


Btw, don't use jQuery for this, jQuery is much, much slower than document.getElementById(), an external function like $() or byId(), or my method: http://jsperf.com/document-getelementbyid-vs-jquery/5

Gilles Castel
  • 876
  • 8
  • 15
1

If you are asking for a shorthand function...

<!DOCTYPE html>
<html>

<body>
The content of the body element is displayed in your browser.
<div id="d1">DIV</div>
<script>
var d=document;
d.g=document.getElementById;
d.g("d1").innerHTML = "catch";
</script>
</body>

</html>

or

<!DOCTYPE html>
<html>

<body>
The content of the body element is displayed in your browser.
<div id="d1">DIV</div>
<script>
var w=window;
w["d1"].innerHTML = "catch2";
</script>
</body>

Lumic
  • 43
  • 2
1

Arrow functions make is shorter.

var $id = (id) => document.getElementById(id);
wiktor
  • 1,425
  • 13
  • 11
1

wrap the document.querySelectorAll ... a jquery like select

function $(selector){
   var s = document.querySelectorAll(selector); 
   return s.length > 1 ? s : s[0];
}

// usage: $('$myId')
  • Oh, but this looks a bit difficult to work with. The function could either return undefined, an HTMLElement or a NodeList. Of course when you use it to get an element by its id `$('#myId')` then it should usually return that HTMLElement, because you hopefully assigned that id exactly once. But if you would use it with queries that *might* match multiple elements it gets cumbersome. – Robert Jun 26 '17 at 02:07
1

If this is on your own site, consider using a library like jQuery to give you this and many other useful shorthands that also abstract away browser differences. Personally, if I wrote enough code to be bothered by the longhand, I would include jQuery.

In jQuery, the syntax would be $("#someid"). If you then want the actual DOM element and not the jQuery wrapper, it's $("#someid")[0], but you could most likely do whatever you're after with the jQuery wrapper.

Or, if you're using this in a browser developer console, research their built-in utilities. As someone else mentioned, the Chrome JavaScript console includes a $("someid") method, and you can also click an element in the developer tools "Elements" view and then reference it with $0 from the console. The previously selected element becomes $1 and so on.

Henrik N
  • 14,212
  • 3
  • 72
  • 116
1

If the only issue here is typing, maybe you should just get yourself a JavaScript editor with intellisense.

If the purpose is to get shorter code, then you could consider a JavaScript library like jQuery, or you can just write your own shorthand functions, like:

function byId(string) {return document.getElementById(string);}

I used to do the above for better performance. What I learnt last year is that with compression techniques the server does it automatically for you, so my shortening technique was actually making my code heavier. Now I am just happy with typing the whole document.getElementById.

Christophe
  • 24,147
  • 23
  • 84
  • 130
0

Another wrapper:

const IDS = new Proxy({}, { 
    get: function(target, id) {
        return document.getElementById(id); } });

IDS.camelCaseId.style.color = 'red';
IDS['dash-id'].style.color = 'blue';
<div id="camelCaseId">div 1</div>
<div id="dash-id">div 2</div>

This, in case you don't want to use the unthinkable, see above.

Mike C.
  • 101
  • 3
0

You can use a wrapper function like :

const byId = (id) => document.getElementById(id);

Or

Assign document.getElementById to a variable by binding it with document object.

const byId = document.getElementById.bind(document);

Note: In second approach, If you don't bind document.getElementById with document you'll get error :

Uncaught TypeError: Illegal invocation

What Function.bind does is it creates a new function with its this keyword set to value that you provide as argument to Function.bind.

Read docs for Function.bind

Omkar76
  • 944
  • 1
  • 5
  • 18
0

Well, if the id of the element does not compete with any properties of the global object, you don't have to use any function.

myDiv.appendChild(document.createTextNode("Once I was myDiv. "));
myDiv.id = "yourDiv";
yourDiv.appendChild(document.createTextNode("But now I'm yourDiv."));

edit: But you don't want to make use of this 'feature'.

Robert
  • 2,435
  • 23
  • 24
  • :( That sounds like browser abuse to me. Show me where this is valid in the HTML5 spec. – Raynos Jun 20 '11 at 22:47
  • 1
    @Raynos: http://dev.w3.org/html5/spec/browsers.html#named-access-on-the-window-object But: "It is possible that this will change. Browser vendors are considering limiting this behaviour to quirks mode." Works in my FF4 and IE8 though. – Robert Jun 20 '11 at 23:56
  • 2
    yes it works right now but it feels dirty and I wouldn't be suprised if it's get deprecated by the end of the year. – Raynos Jun 21 '11 at 07:43
  • @Raynos I hope so. I don't like browsers to pollute the global namespace. But on the other hand this wasn't such a bad thing when it was invented. (when webpages were html-centric and javascript was a nice feature) – Robert Jun 28 '11 at 14:49
-1

I wrote this yesterday and found it quite useful.

function gid(id, attribute) {
    var x = 'document.getElementById("'+id+'")';
    if(attribute) x += '.'+attribute;
    eval('x =' + x);
    return x;
}

This is how you use it.

// Get element by ID
   var node = gid('someID'); //returns <p id='someID' class='style'>Hello World</p>

// returns 'Hello World'
// var getText = document.GetElementById('someID').innerText; 
   var getText = gid('someID', 'innerText'); 

// Get parent node
   var parentNode = gid('someID', 'parentNode');
  • This is not a good usage of eval. There's nothing about getting the element that needs eval, and you can dynamically get a property with bracket notation. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors – ThatsNoMoon Jul 17 '20 at 11:56