Christian Heilmann

Shorter DOMscript via cloning vs. generating elements

Thursday, December 8th, 2005 at 4:19 pm

cloned sheepI just looked through some of my older scripts and other people’s code and realised that a lot of time we bloat our methods by repeating the same functionality.

This is especially true when it comes to generating a lot of HTML via the DOM.

We keep repeating the same document.createElement and setAttribute lines over and over. Wouldn’t it be more efficient to create those once when initialising our script and then cloning them?

Say for example we need to generate three links that are dependent on JavaScript (and we should generate these via JS).

A normal method to do this would be:


// 30 lines of code
createLinks:function(){
var newul,newli,newa;
newul=document.createElement('ul');
newli=document.createElement('li')
// sheep #1
newa=document.createElement('a');
newa.appendChild(document.createTextNode('baa#1'));
newa.href='#';
dolly.addEvent(newa,'click',dolly.baa1);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// sheep #2
newli=document.createElement('li')
newa=document.createElement('a');
newa.appendChild(document.createTextNode('baa#2'));
newa.href='#';
dolly.addEvent(newa,'click',dolly.baa2);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// sheep #3
newli=document.createElement('li')
newa=document.createElement('a');
newa.appendChild(document.createTextNode('baa#3'));
newa.href='#';
dolly.addEvent(newa,'click',dolly.baa3);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

Now, if part of the initialisation method would be to generate a dummy link inside an LI, we could reuse by cloning it:


makeClones:function(){
dolly.li=document.createElement('li');
dolly.a=document.createElement('a');
dolly.a.appendChild(document.createTextNode('baa!'));
dolly.a.setAttribute('href','#');
dolly.li.appendChild(dolly.a);
},

By cloning this dummy li and referencing the link via firstChild and the link text via firstChild.firstChild we can save 9 lines of code, which still means a 4 line win if add the createClones method:


// 21 lines + 5 lines createClones
createFlock:function(){
var newli,newa,newul;
newul=document.createElement('ul');
// sheep #1
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,'click',dolly.baa1);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue='baa#1';
newul.appendChild(newli);
// sheep #2
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,'click',dolly.baa2);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue='baa#2';
newul.appendChild(newli);
// sheep #3
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,'click',dolly.baa3);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue='baa#3';
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

Further reduction could be achieved by moving the event handling and text changing to another helper method:


dressClone:function(clone,func,name){
dolly.addEvent(clone.firstChild,'click',func);
clone.firstChild.onlick=function(){return false;} // Hello Safari
clone.firstChild.firstChild.nodeValue=name;
},

Which means the main method for generating the links will be 23 lines in total (including the helper methods):


// 15 lines + 5 lines + 3 lines
createWoolyFlock:function(){
var newli,newa,newul;
newul=document.createElement('ul');
// sheep #1
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa1,'baa#1');
newul.appendChild(newli);
// sheep #2
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa2,'baa#2');
newul.appendChild(newli);
// sheep #3
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa3,'baa#3');
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

The benefits are the following:

  • We have one centralised spot for defining the links initially – if for example we needed to add a class at a later state we’d do it in one method instead of scanning the whole object of where to apply the changes
  • Generating a new LI is now 3 lines of code instead of 7, which multiplies with the amount of links
  • We don’t need to re-define a lot of variables or create new ones every time we add a link.

The example script of cloning vs. generating works on MSIE 6, Firefox, Opera 8 and Safari.

Is there any problem or bad effect I am overlooking? How is the performance of cloning vs. generating anew every time we need a link?

Share on Mastodon (needs instance)

Share on BlueSky

Newsletter

Check out the Dev Digest Newsletter I write every week for WeAreDevelopers. Latest issues:

Word is Doomed, Flawed LLM benchmarks, hard sorting and CSS mistakes Spot LLM benchmark flaws, learn why sorting is hard, how to run Doom in Word and how to say "no" like a manager.
30 years of JS, Browser AI, how attackers use GenAI, whistling code Learn how to use AI in your browser and not on the cloud, why AI makes different mistakes than humans and go and whistle up some code!
197: Dunning-Kruger steroids, state of cloud security, puppies>beer
196: AI killed devops, what now? LLM Political bias & AI security Learn how AI killed DevOps, create long tasks in JS, why 1 in 5 security breaches are AI generated code & play "The Scope Creep"
195: End of likes, JS Zoo and Tim Berners-Lee doesn't see AI vs Web Meta kills like buttons, Tim-Berners-Lee thinks AI won't kill the web, GitHub is ending toasts and the worst selling Microsoft product.

My other work: