<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<script type="text/javascript">
// <![CDATA[
function testFunction (n, f) {
	var start = new Date();
	for (var i = 0; i < n; i++) { f(); }
	return new Date().getTime() - start.getTime();
}

function compareAll (n, funcs) {
	var fns = new Array();
	var times = {};

	document.write("<ul>");
	for (var fn in funcs) {
		var f = funcs[fn];
		if (f) {
			var t = testFunction(n, f);
			fns.push(fn);
			times[fn] = t;
			document.write("<li>" + fn + " x " + n + ": " + t + " ms</li>");
		}
	}
	document.write("</ul>");

	fns.sort(function (a, b) { return times[b] - times[a]; });

	document.write("<table border=1>");
	document.write("<tr>");
	document.write("<th> </th>");
	document.write("<th>Rate</th>");
	for (var i in fns) {
		var fn = fns[i];
		document.write("<th>" + fn + "</th>");
	}
	document.write("</tr>");
	for (var i in fns) {
		var fn = fns[i];
		var ft = times[fn];

		document.write("<tr>");
		document.write("<th>" + fn + "</th>");
		document.write("<td>" + Math.round(n / (times[fn] / 1000)) + "/s</td>");

		for (var j in fns) {
			var fn2 = fns[j];

			var cmp;
			if (fn == fn2) {
				cmp = "--";
			} else {
				var ft2 = times[fn2];
				var diff = (ft2 - ft) / ft2;
				cmp = (diff > 0 ? "+" : "");
				cmp += Math.round(1000 * diff) / 10;
				cmp += "%";
			}

			document.write("<td>" + cmp + "</td>");
		}

		document.write("</tr>");
	}
	document.write("</table>");
}
//]]>
</script>
</head>
<body>
<div id="test" class="a b c d e f g h i"/>

<script type="text/javascript">
// <![CDATA[
var hasClass1 = (function () {
	var reCache1 = {};
	function getRegex(className) {
		if (reCache1[className]) return reCache1[className];

		var re = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)");
		reCache1[className] = re;
		return re;
	}

	return function (element, className) {
		return element.className.match(getRegex(className));
	};
})();

function hasClass2 (element, className) {
	return element.className.match(
		new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"));
}

function hasClass3 (element, className) {
  var Classes = element.className.split( " " );
  for ( var i = 0; i < Classes.length; i++ ) {
	if ( Classes[i] == className ) {
	  return ( true );
	}
  }
  return ( false );
}

var hasClass4 = (function () {
	var reCache2 = {};
	return function (element, className) {
		var re = reCache2[className];
		if (!re) {
			re = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)");
			reCache2[className] = re;
		}

		return element.className.match(re);
	};
})();

function hasClass5 (element, className) {
	return element.className.match(
		new RegExp("(\\s|^)" + className + "(\\s|$)"));
}

var hasClass9 = (function () {
	var reCache6 = {};
	return function (element, className) {
		return (reCache6[className] ? reCache6[className] : (reCache6[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
	};
})();

var test = document.getElementById("test");

compareAll(10000, {
	"re+cache": function () { hasClass1(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) },
	"re+nocache": function () { hasClass2(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) },
	"split": function () { hasClass3(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) },
	"re+nocache+capture": function () { hasClass5(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) },
	//"re+literal": function () { test.className.match(/(?:^|\s)d(?:$|\s)/) },
	"re+cache+onefunc4": function () { hasClass4(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) },
	"re+cache+onefunc9": function () { hasClass9(test, String.fromCharCode(97 + Math.round(Math.random() * 25))) }
});
//]]>
</script>
</body>
</html>