この記事はJ2complexed Advent Calendar 2016の10日目です。
#DOMをprototypeで拡張してみよう
ArrayやObjectをprototypeで拡張してしまうとfor inループで意図しないメソッドが挙がってしまいました。(人これを、プロトタイプ汚染という)
参考:プロトタイプ汚染とループ
ですが、DOMのprototypeを精査するようなことはまずないので、DOMだけはprototypeで拡張してしまいましょう。1
なお、ここではES5の記述でいきます。ES2015でもそのまま使えます。
##addClass,removeClassを実装
jQueryで頻出するメソッドです。
###addClass
Element.prototype.addClass = function(classname) {
if(classname == null || classname typeof classname !== "string") return this;
var parse = classname.split(" "),
len = parse.length;
for(len;len--;) {
this.classList.add(parse[len]);
}
return this;
};
var el = document.querySelector("#identify"); // <div id="identify"></div>
el.addClass("hoge"); // <div id="identify" class="hoge"></div>
###removeClass
Element.prototype.removeClass = function(classname) {
if(classname == null || classname typeof classname !== "string") return this;
var parse = classname.split(" "),
len = parse.length;
for(len;len--;) {
this.classList.remove(parse[len]);
}
return this;
};
var el = document.querySelector(".hoge"); // <div class="hoge foo bar"></div>
el.removeClass("foo"); // <div class="hoge bar"></div>
同じ要領でhasClass
も作れます。
Elementに対してaddClass,hassClass
はぶっちゃけコードにもあるようにclassList
を使えば済みます。
ですが、NodeListやHTMLCollectionそのものにclassList
はないのでループさせる必要があります。なのでNodeListにaddClass,removeClass
を拡張してしまうのが便利です。
##NodeListにaddClass,removeClassを実装
※Elementが拡張されてる前提のコードです。
###addClass
NodeList.prototype.addClass = function(classname) {
[].forEach.call(this, function(el) {
el.addClass(classname);
});
};
var div = document.querySelectorAll("div"); // [<div></div>, <div></div>];
div.addClass("hoge"); // [<div class="hoge"></div>,<div class="hoge"></div>];
###removeClass
NodeList.prototype.addClass = function(classname) {
[].forEach.call(this, function(el) {
el.removeClass(classname);
});
};
var div = document.querySelectorAll(".hoge"); // [<div class="hoge"></div>, <div class="hoge"></div>];
div.addClass("hoge"); // [<div></div>,<div></div>];
-
ただし将来的に同じ名前のメソッドが実装された場合、それをオーバーライドしてしまうので注意です。 ↩