Pour répondre a ce probleme, j'ai pris 4 approches différentes. On considere pour la démonstration que nos élements n'ont qu'une seule class (ce qui n'est pas forcement le cas en pratique), et que on doit commencer a chercher des la racine du document, pas apres. On ne prend pas non plus en compte les différences en terme d'occupation mémoire, ca sera pour un autre article.

Note: tous ces examples ont été testés uniquement avec Firefox. Ils devraient marcher avec des modifications mineures dans tous les autres navigateurs, a l'exception d'IE.sci

getElementsByTagName()

C'est la méthode la plus naive. On fait un getElementsByTagName('div'), et on regarde l'attribut .className de chaque résultat pour oui ou non l'ajouter dans un tableau final. Le code:

function getComments()
{
	var a   = document.getElementsByTagName('div');
	var len = a.length;
	var out = new Array();
	
	for (var i = 0; i < len; i++)
	{
		if (a[i].hasAttribute('class') && a[i].className == "comment")
			out.push(a[i]);
	}
	return out;
}

Parseur maison

Code écrit a l'origine par Daniel Glazman un jour ou j'avais donné la méthode naive a quelqu'un qui cherchait un getElementsByClassName(). On parse notre document recursivement et quand on trouve ce qu'on cherche, on l'ajoute directement.

function getComments()
{
	function _GetElementsByClass(outArray, seed)
	{
		while (seed)
		{
			if (seed.nodeType == Node.ELEMENT_NODE)
			{
				if (seed.hasAttribute("class") && seed.className == "comment")
					outArray.push(seed);
				_GetElementsByClass(outArray, seed.firstChild)
			}
			seed = seed.nextSibling;
		}
	}
	
	var outArray = new Array();
	_GetElementsByClass(outArray, document.documentElement);
	return outArray;
}

TreeWalker

A mon avis le plus lisible et le plus flexible: meme sans connaitre on devine ce que fait le code du premier coup d'oeil, et c'est simple a modifier Par ailleurs, on utilise un truc implémenté nativement par le navigateur, on devrait donc etre rapide. Voir plus bah pour la meme chose en plus complexe.

function getComments()
{
	function acceptNode(node)
	{
		if (node.hasAttribute("class") && node.className == "comment")
		{
				return NodeFilter.FILTER_ACCEPT;
		}
		return NodeFilter.FILTER_SKIP;
	}
	
	var out        = new Array();
	var treeWalker = document.createTreeWalker(document.body, 
	                                           NodeFilter.SHOW_ELEMENT,
	                                           acceptNode,
	                                           false);
	if (treeWalker)
	{
		var node = treeWalker.nextNode();
		
		while (node)
		{
			out.push(node);
			node = treeWalker.nextNode();
		}
	}
	return out;
}

XPath

Donné par Dylan Schiemann en réponse au post de Daniel sur les différentes méthodes de getElementsByClassName, et redonné par Dam lors de mon récent post sur le TreeWalker et Konqueror, on profite du fait que on manipule du XML, et on utilise XPath.

function getComments()
{
	var xpathResult = document.evaluate('//*[@class = "comment"]', document, null, 0, null);
	var outArray = new Array();
	var item; 
	
	while (item = xpathResult.iterateNext())
	{
		outArray[outArray.length] = item;
	}
	return outArray;
}

Voyons ce que cela donne. Chaque script a été relancé 10 fois sur un gros (> 700 commentaires) article de linuxfr tres legement nettoyé, et le cache vidé entre chaque essai. C'est loin d'etre une méthode tres scientifique, mais ca suffira ici. Les temps sont exprimés en millisecondes, meme si cela n'est pas tres important vu que par flemme je ne donnerais ni les pages ni les specs de la machine sur laquelle j'ai fait tourner tout :-)

  1. Résultat pour getElementsByTagName(): 200
  2. Résultat pour Parseur maison: 5000
  3. Résultat pour TreeWalker: 2400
  4. Résultat pour XPath: 180

(Rappel: je ne teste pas les différentes implémentations de getElementsByClassName. Je teste différentes manieres d'utiliser le DOM pour récupérer des commentaires sur linuxfr, en simpliant grandement. Ces chiffres sont donc a prendre avec des pincettes, ils servent surtout a annoncer d'autres méthodes dans la suite de ce post :-)

Les résultats sont plutot interessants. J'ai bien tout verifié pour etre sur que je n'hallucinais pas. Vu que c'est pas tellement ce que j'attendais, les conclusions attendront: je vais passer un peu de temps à regarder ce que je peux faire sur la DLFPToolbar au vu de ces résultats.

Edit: Visiblement, je suis pas le seul à m'interesser au probleme. La version svn de prototype a l'air excellente.