htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

jQueryのような $ を使えるようにするスニペット作ってみた

jQuery$() 関数はすごく便利です。
prototype.js にも似たようなのがありますが、使ったことがないので割愛。

ともあれ、jQueryのアレを使うような感じで $ を使えるようにするスニペットを書いてみました。

var $ = function(str, target){
  if (typeof str!=="string") {
    throw new Error("引数が不正です。");
  }
  var element = target || document;
  
  // idの場合は素直にそのまま処理
  if (str[0]==="#") {
    return element.getElementById(str.slice(1));
  }
  // classの場合はメソッドの実装状況に応じて場合分け
  else if (str[0]===".") {
    // getElementsByClassName はHTML5で定義されているので比較的新しいブラウザが実装している
    if (element.getElementsByClassName) {
      return element.getElementsByClassName(str.slice(1));
    }
    // IE8には Selectors API があり、これで代用できる
    else if (element.querySelectorAll) {
      return element.querySelectorAll(str);
    }
    // Selectors APIも存在しない場合は妥協して配列で返す
    else {
      (function(){
        var arr = [];
        var collection = element.getElementsByTagName("*");
        // classNameに str を含んでいれば arr にpushする
        for (var i=0, l=collection.length; i<l; i++) {
          if (function(){
            // classNameに一致するものがあれば True
            var tmp = collection[i].className.split(" ");
            for (var i=0, l=tmp.length; i<l; i++) {
              if (tmp[i]===str.slice(1)) {
                return true;
              }
            }
            return false;
          }()) {
            arr.push(collection[i]);
          }
        }
        return arr;
      })();
    }
  }
  // idでもclassでもなければtagName
  else {
    return element.getElementsByTagName(str);
  }
};

見ての通り、返ってくるオブジェクトはjQueryオブジェクトのような殻で覆われたものではなく、そのものです。


使い方はjQueryに準じて実装したつもりなので、たぶん簡単だと思います。
第一引数に取り出したい対象を、第二引数は取り出す範囲を絞り込みたいときに任意で指定します。

$("#hoge") でidがhogeの HTMLElement を返します。

$("a") で、ドキュメント全体から全ての A要素を含んだ NodeList(もしくは HTMLCollection)を返します。

$(".fuga") でclassがfugaの NodeList(もしくは HTMLCollection)をすべて返します。
これも基本的には上記2つと同じように使えますが、 Element#getElementsByClassName にも Element#querySelectorAll にも対応していないブラウザでは例外的に Array 型が返るようになっています。


【たとえば】

<body>
  <div id="head">
    <div id="logo">
      <img src="./hoge.gif" alt="logo" />
    </div>
    <ul id="topmenu">
      <li class="menuitem"><a href="01.html">ほげほげ</a></li>
      <li class="menuitem"><a href="02.html">ふがふが</a></li>
      <li class="menuitem"><a href="03.html">ぴよぴよ</a></li>
    </ul>
  </div>
  <div id="main">
--------(省略)--------
  </div>
</body>

とあったとします。
そのとき、

// ロゴを書き換えたい!
$("img", $("#logo"))[0].src = "./fuga.gif";

// メニューアイテムの中身を空っぽにしたい!
var li = $("li", $("#topmenu"));
for (var i=0, len=li.length; i<len; i++) {
  $("#topmenu").appendChild(li[i].cloneNode(false));
  $("#topmenu").removeChild(li[i]);
}

なんて書けるわけです。

正直、初めから素直にjQuery使っとけと思いますが、動作速度的に若干有利かなと。
個人的には使っていきたいです。