はじめに
no conflict(競合しない)という位なんだから、「名称」なのか「処理」なのかわからんが
何かしらを競合しないように整備してくれているんだろう。。。
としか思っていなかったので、この”おまじない”を今更紐解いてみる。
そもそも何と競合しているのか
ざっと調べると、解説しているほぼ全てのページで、prototype.jsが例として挙げられていた。
prototype.jsはMITライセンスで使用可能なライブラリで、
Prototype JavaScript Framework は、Sam Stephenson が開発したJavaScriptフレームワークであり、Ajaxフレームワークやその他のユーティリティを提供する。
との事(参考:Wikipedia)。
jQueryも幅広く利用可能だが、prototype.jsも広範囲をカバーしているライブラリのようだ。
そしてこちらのサイトで詳しく記載されているが、グローバルの名前空間に
幾つかオブジェクトを定義しており、その中に「$」が使用されているとの事。
ちなみに「document.getElementById」
つまり、prototype.jsとjQueryを同時に使用した場合、
prototype.jsがグローバルに定義した「$」と、jQueryのエイリアスである「$」が
競合してしまう(というように理解した)。
競合させてみる
「競合」とはどのような状態を指すのか、試してみたいと思う。
ブログタイトルが設定されたテキストフィールドしか存在しない質素すぎるページ。
これをサンプルとする。
index.html
<input type="text" id="conflict-textfield" value="trial and error">
// jQueryでテキストフィールドの値を取得 console.log($('#conflict-textfield').val()); // prototype.jsでテキストフィールドの値を取得 console.log($('conflict-textfield').value);
jQuery ⇒ prototype.js の順で読み込み
jQuery⇒prototype.jsの順にライブラリを読み込みます。
index.html
<!-- jQuery --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- prototype.js --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.min.js"></script> <!-- 2つのライブラリを使用するJavaScript --> <script type="text/javascript" src="./js/conflict.js"></script>
実行結果
jQueryの値取得 val()でエラーになりました。
// jQueryでテキストフィールドの値を取得 // console.log('jQuery で値を取得 ⇒ ' + $('#conflict-textfield').val()); // prototype.jsでテキストフィールドの値を取得 console.log('prototype.js で値を取得 ⇒ ' + $('conflict-textfield').value);
実行結果
prototype.jsでは正常に値を取得できている。
両方のライブラリがエイリアス「$」を使おうとして競合していると言えます。
prototype.js ⇒ jQuery の順で読み込み
prototype.js ⇒ jQuery の順にライブラリを読み込みます。
index.html
<!-- prototype.js --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.min.js"></script> <!-- jQuery --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- 2つのライブラリを使用するJavaScript --> <script type="text/javascript" src="./js/conflict.js"></script>
実行結果
今度はprototype.jsでエラーになりました。
後から読み込んだjQueryに「$」が上書きされている事によるエラーと思われる。
解決策
そこで出てくるのが jQuery.noConflict()
これはjQueryがエイリアスとして定義している「$」を”解放”し、競合を防ぐというもの。
jQuery.noConflict()実行後は、「jQueryオブジェクト」のエイリアスである「$」を解放するので、「jQuery」と明示する必要があります。
それを踏まえて conflict.js を修正します。
conflict.js
jQuery.noConflict(); // jQueryでテキストフィールドの値を取得 console.log('jQuery で値を取得 ⇒ ' + jQuery('#conflict-textfield').val()); // prototype.jsでテキストフィールドの値を取得 console.log('prototype.js で値を取得 ⇒ ' + $('conflict-textfield').value);
1行目でjQuery.noConflict()を実行し、
3行目で「$」ではなく「jQuery」で実行するように修正しています。
実行結果
jQuery、prototype.js 両方で正常に値を取得できました。
または即時関数を使用して
jQuery.noConflict(); // jQueryでテキストフィールドの値を取得 // console.log('jQuery で値を取得 ⇒ ' + jQuery('#conflict-textfield').val()); (function($) { console.log('jQuery で値を取得 ⇒ '+$('#conflict-textfield').val()); })(jQuery); // prototype.jsでテキストフィールドの値を取得 console.log('prototype.js で値を取得 ⇒ ' + $('conflict-textfield').value);
このようにすることもできます。
個人的にはこの方がスマートのように思います。