The first problem with both your examples is that they are hard-wiring references to either the id #messages
or the DOM element messages
. That's easy enough to solve in the first example, by making id
a parameter. Since it's no longer specific to messages, we'll also rename it:
function emptyById(id) {
while ($(id).lastChild) {
$(id).removeChild($(id).lastChild);
}
}
It's obvious that one does not want to look up the element over and over again. Beyond performance, it is duplicative and error-prone. Therefore, it should obviously be rewritten as
function emptyById(id) {
var elt = $(id);
while (elt.lastChild) elt.removeChild(elt.lastChild);
}
However, the problem with this approach is that it mixes two entirely separate problems:
Finding an element with a particular ID.
Performing some operation on this element (in this case, removing its children).
In practical terms, assume you have an element, whose children you want to remove. Given the above design, you are forced to say
emptyById(elt.id)
which won't even work if the element does not happen to have an ID.
Therefore, it is much better design to follow your second example, and define the interface via the DOM element not its ID (rewriting the loop slightly):
function emptyChildren(elt) {
var last;
while (last = elt.lastChild) elt.removeChild(last);
}
Now, if you have the element you can simply call emptyChildren(elt)
; if you have the ID, you can call emptyChildren($(id))
.
None of this is really about performance. getElementById
is fast enough that you would not notice if you called it ten times when you really only needed to call it once--assuming, of course, that this is not in a tight loop being executed one million times. The important question is how to design your interfaces to be general and flexible.