Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DerekZiemba/c185438a207d2d66f0962ae8d080e54a to your computer and use it in GitHub Desktop.
Save DerekZiemba/c185438a207d2d66f0962ae8d080e54a to your computer and use it in GitHub Desktop.
Native ClassList Performance vs Polyfills (http://jsbench.github.io/#c185438a207d2d66f0962ae8d080e54a) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Loop Performance .jsbench</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<script src="./suite.js"></script>
</head>
<body>
<h1>Open the console to view the results</h1>
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2>
</body>
</html>
"use strict";
(function (factory) {
if (typeof Benchmark !== "undefined") {
factory(Benchmark);
} else {
factory(require("benchmark"));
}
})(function (Benchmark) {
var suite = new Benchmark.Suite;
Benchmark.prototype.setup = function () {
// var NativeClassList = Object.getOwnPropertyDescriptor(Element.prototype, 'classList');
// var nativeTokenListProto = DOMTokenList.prototype;
if (!Element.prototype.classListMDN) {
var MDNClassList = (function ClassListBasicFromMDN() {
function regExp(name) { return new RegExp('(^| )' + name + '( |$)'); };
function forEach(list, fn, scope) { for (var i = 0; i < list.length; i++) { fn.call(scope, list[i]); } };
function ClassList(element) {
this.element = element;
}
ClassList.prototype = {
add: function () {
forEach(arguments, function (name) {
if (!this.contains(name)) { this.element.className += ' ' + name; }
}, this);
},
remove: function () {
forEach(arguments, function (name) {
this.element.className = this.element.className.replace(regExp(name), ' ');
}, this);
},
toggle: function (name, bool) {
var bHas = this.contains(name);
if (bool == null) {
return bHas ? (this.remove(name), false) : (this.add(name), true);
} else if (bool) {
if (!bHas) { this.element.className += ' ' + name; }
return true;
}
return (this.remove(name), false);
},
contains: function (name) { return regExp(name).test(this.element.className); },
replace: function (oldName, newName) { this.remove(oldName); this.add(newName); },
toString: function () { return this.element.className; },
get values() { return this.element.className.split(/\s+/).filter(function (x) { return x; }); },
get value() { return this.element.className; },
set value(value) { this.element.className = value; },
get length() { return this.values.length; },
};
return ClassList;
})();
// delete Element.prototype.classList;
Object.defineProperty(Element.prototype, 'classListMDN', {
configurable: true, enumerable: true,
get: function () { return new MDNClassList(this); },
// set: function (value) { this.classListMDN.value = value.value; }
});
}
if (!Element.prototype.classListMy) {
var MyClassList = (function ClassListBasicFromMDN() {
var cache = {};
function regExp(name) {
var rgx = cache[name];
if (!rgx) { rgx = cache[name] = new RegExp('(^| +)' + name + '( +|$)'); };
return rgx;
};
function ClassList(element) {
this.element = element;
}
ClassList.prototype = {
add: function () {
for (var i = 0, len = arguments.length; i < len; i++) {
if (!this.contains(arguments[i])) { this.element.className += ' ' + arguments[i]; }
}
},
remove: function () {
for (var i = 0, len = arguments.length; i < len; i++) {
this.element.className = this.element.className.replace(regExp(arguments[i]), ' ');
}
},
toggle: function (name, bool) {
var bHas = this.contains(name);
if (bool == null) {
return bHas ? (this.remove(name), false) : (this.add(name), true);
} else if (bool) {
if (!bHas) { this.element.className += ' ' + name; }
return true;
}
return (this.remove(name), false);
},
contains: function (name) { return regExp(name).test(this.element.className); },
replace: function (oldName, newName) { this.remove(oldName); this.add(newName); },
toString: function () { return this.element.className; },
get values() { return this.element.className.split(/\s+/).filter(function (x) { return x; }); },
get value() { return this.element.className; },
set value(value) { this.element.className = value; },
get length() { return this.values.length; },
};
return ClassList;
})();
Object.defineProperty(Element.prototype, 'classListMy', {
configurable: true, enumerable: true,
get: function () { return new MyClassList(this); },
// set: function (value) { this.classListMy.value = value.value; }
});
DOMTokenList.prototype.replace = MyClassList.prototype.replace;
};
if (document.getElementById('testelem')) {
document.body.removeChild(document.getElementById('testelem'));
}
divThing = window.divThing = document.createElement('div');
divThing.className = " thing id-t3_61ruov linkflair-story linkflair odd link self";
divThing.id = "testelem";
document.body.appendChild(divThing);
};
Benchmark.prototype.teardown = function () {
};
suite.add("default Native", function () {
//default Native
// var divThing = document.getElementById('testelem');
var value = divThing.classList.toString();
var len = divThing.classList.length;
divThing.classList.add('added');
divThing.classList.toggle('nonexistant', false);
divThing.classList.toggle('exists', true);
divThing.classList.toggle('oddball');
divThing.classList.replace('oddball', 'exists');
divThing.classList.toggle('oddball');
divThing.classList.remove('added');
divThing.classList.toggle('exists', false);
divThing.classList.toggle('oddball');
divThing.classList.remove('linkflair');
divThing.classList.replace('odd', 'linkflair');
divThing.classList.replace('link', 'odd');
divThing.classList.add('link');
if (len !== divThing.classList.length) {
throw new DOMException("###############" + value + " |#####################| " + divThing.classList.toString());
}
// if (value !== divThing.ClassList.toString()) {
// throw new DOMException(value + " |#####################| " + divThing.classList.toString());
// }
});
suite.add("MDN", function () {
//MDN
// var divThing = document.getElementById('testelem');
var value = divThing.classListMDN.toString();
var len = divThing.classListMDN.length;
divThing.classListMDN.add('added');
divThing.classListMDN.toggle('nonexistant', false);
divThing.classListMDN.toggle('exists', true);
divThing.classListMDN.toggle('oddball');
divThing.classListMDN.replace('oddball', 'exists');
divThing.classListMDN.toggle('oddball');
divThing.classListMDN.remove('added');
divThing.classListMDN.toggle('exists', false);
divThing.classListMDN.toggle('oddball');
divThing.classListMDN.remove('linkflair');
divThing.classListMDN.replace('odd', 'linkflair');
divThing.classListMDN.replace('link', 'odd');
divThing.classListMDN.add('link');
if (len !== divThing.classListMDN.length) {
throw new DOMException("###############" + value + " |#####################| " + divThing.classListMDN.toString());
}
});
suite.add("My", function () {
//My
// var divThing = document.getElementById('testelem');
var value = divThing.classListMy.toString();
var len = divThing.classListMy.length;
divThing.classListMy.add('added');
divThing.classListMy.toggle('nonexistant', false);
divThing.classListMy.toggle('exists', true);
divThing.classListMy.toggle('oddball');
divThing.classListMy.replace('oddball', 'exists');
divThing.classListMy.toggle('oddball');
divThing.classListMy.remove('added');
divThing.classListMy.toggle('exists', false);
divThing.classListMy.toggle('oddball');
divThing.classListMy.remove('linkflair');
divThing.classListMy.replace('odd', 'linkflair');
divThing.classListMy.replace('link', 'odd');
divThing.classListMy.add('link');
if (len !== divThing.classListMy.length) {
throw new DOMException("###############" + value + " |#####################| " + divThing.classListMy.toString());
}
});
suite.add("cached Native", function () {
//cached Native
// var divThing = document.getElementById('testelem');
var cls = divThing.classList;
var value = cls.toString();
var len = cls.length;
cls.add('added');
cls.toggle('nonexistant', false);
cls.toggle('exists', true);
cls.toggle('oddball');
cls.replace('oddball', 'exists');
cls.toggle('oddball');
cls.remove('added');
cls.toggle('exists', false);
cls.toggle('oddball');
cls.remove('linkflair');
cls.replace('odd', 'linkflair');
cls.replace('link', 'odd');
cls.add('link');
if (len !== cls.length) {
throw new DOMException("###############" + value + " |#####################| " + cls.toString());
}
});
suite.add("cached MDN", function () {
//cached MDN
// var divThing = document.getElementById('testelem');
var cls = divThing.classListMDN;
var value = cls.toString();
var len = cls.length;
cls.add('added');
cls.toggle('nonexistant', false);
cls.toggle('exists', true);
cls.toggle('oddball');
cls.replace('oddball', 'exists');
cls.toggle('oddball');
cls.remove('added');
cls.toggle('exists', false);
cls.toggle('oddball');
cls.remove('linkflair');
cls.replace('odd', 'linkflair');
cls.replace('link', 'odd');
cls.add('link');
if (len !== cls.length) {
throw new DOMException("###############" + value + " |#####################| " + cls.toString());
}
});
suite.add("cached My", function () {
//cached My
// var divThing = document.getElementById('testelem');
var cls = divThing.classListMy;
var value = cls.toString();
var len = cls.length;
cls.add('added');
cls.toggle('nonexistant', false);
cls.toggle('exists', true);
cls.toggle('oddball');
cls.replace('oddball', 'exists');
cls.toggle('oddball');
cls.remove('added');
cls.toggle('exists', false);
cls.toggle('oddball');
cls.remove('linkflair');
cls.replace('odd', 'linkflair');
cls.replace('link', 'odd');
cls.add('link');
if (len !== cls.length) {
throw new DOMException("###############" + value + " |#####################| " + cls.toString());
}
});
suite.on("complete", function (evt) {
console.log(new Array(30).join("-"));
var results = evt.currentTarget.sort(function (a, b) {
return b.hz - a.hz;
});
results.forEach(function (item) {
console.log((idx + 1) + ". " + item);
});
});
console.log("Native ClassList Performance vs Polyfills");
console.log(new Array(30).join("-"));
suite.run();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment