先日、画像を左右にスワイプできるslider系のjQueryライブラリを利用していた時、標準のjQueryには存在しないメソッドを呼び出すことで、ライブラリ専用のインスタンスを取得でき、そのインスタンスを利用することで様々なメソッドにアクセスできる、というものがありました。

そこで、自分もjQueryを拡張してみようと思い、真似をして以下の様なコードを書いてみました。

$.fn.extend({
  slider: function(){
    var idx = 0;
    this.method = function(){ return ++idx; };
    return this;
  }
});

var slider = $('body').slider(); // 特にbodyを指定することに意味は無い
slider.method(); // -> 1
slider.method(); // -> 2

うまく実行することが出来ました。

しかし、同じようにもう一度slider()メソッドを利用してインスタンスを取得すると、別のインスタンスになってしまい値はリセットされてしまいます。

var slider = $('body').slider();
slider.method(); // -> 1
slider.method(); // -> 2

slider = $('body').slider();
slider.method(); // -> 1
slider.method(); // -> 2

この場合、複雑なシステムなどでjsファイルが複数存在する場合、ファイルをまたいで同じインスタンスを利用するには、予めインスタンスを取得しておき、必要なメソッドにインスタンスを渡すというような方法が考えられます。

コード的にはそういった書き方をしたほうが適切なのかもしれません。しかし、いろいろと面倒なので同じDOMで一度呼び出したことがあるインスタンスには同じインスタンスが返ってくるように以下のような更なる別の拡張を追加しました。

window.instances = window.instances || {}

$.extend({ // $.fn.extendではない
  getInstance: function(jqobj){
    if(jqobj.length==0) return undefined;
    return window.instances[jqobj.attr('instance-id')];
  },

  setInstance: function(instance){
    var id = (Math.random()+'').substr(2);
    instance.attr('instance-id', id);
    return window.instances[id] = instance;
  }
});

インスタンスを作成した際にinstance-id属性に乱数を設定たものを割り当て、取得するときにinstance-id属性が存在していれば、idからインスタンスを取得するというわけです。

そして、$.fn.extendのsliderを以下のようにします。

$.fn.extend({
  slider: function(){
    instance = $.getInstance(this);
    if(instance) return instance;

    var idx = 0;
    this.method = function(){ return ++idx; }
    return $.setInstance(this);
  }
});

var slider = $('body').slider();
slider.method(); // -> 1
slider.method(); // -> 2

slider = $('body').slider();
slider.method(); // -> 3
slider.method(); // -> 4

少し無理やりなような気もするのですが、これでどこからでも同じ対象DOMであれば、同じインスタンスを取得することが出来るようになりました。

しかし、なにかしてはいけないことをしている気がして気持ちが悪いです。
皆様は、このような状況をどう感じますでしょうか?

より良い解決策や、アドバイスなどございましたらよろしくお願いいたしますm(_ _)m