- `$`が競合する理由と`noConflict()`の役割
- `$`は特別な記号ではない
- 競合は実際に起きる
- `noConflict()`が何をしているのか
- WordPressが必ずnoConflictを使う理由
- ではどうやってjQueryを書くのか
- よくある誤解
- なぜこの設計が重要なのか
- 注意点:最も危険なコード
- まとめ
`$`が競合する理由と`noConflict()`の役割
jQueryのトラブルの中でも、最も頻出するエラーがあります。
`$ is not a function`
このエラーは「jQueryが読み込まれていない」時だけに出るわけではありません。
むしろ、jQueryは存在しているのに使えない時に出ます。
そしてこの現象の正体が `noConflict()` です。
多くの解説では「他ライブラリと競合するから」とだけ説明されますが、それだけでは不十分です。
本質は、`$` がそもそもjQuery専用の記号ではない、という点にあります。
`$`は特別な記号ではない
JavaScriptでは、次のコードは普通に成立します。
var $ = 123; console.log($);
`$` は予約語でもキーワードでもありません。
単なる変数名です。
つまり、誰でも自由に使えます。
jQueryはこの短い名前を採用したことで、コードを簡潔に書けるようになりました。
$('.box').hide();
しかし同時に問題を生みました。
他のライブラリも同じ変数名を使えるという問題です。
競合は実際に起きる
たとえば、Prototype.js という古いライブラリがあります。
これも `$` を使用します。
$('header');
この `$` は「DOM要素を返す関数」です。
一方、jQueryの `$` は「jQueryオブジェクトを返す関数」です。
同じ記号なのに意味が違います。
もし両方が同時に読み込まれると、後に読み込まれた方が `$` を上書きします。
つまり、jQueryが存在していても、`$` がjQueryを指さなくなります。
これが `$ is not a function` の正体です。
`noConflict()`が何をしているのか
jQueryはこの問題を解決するため、起動時に次の処理を行えます。
jQuery.noConflict();
この関数が行っている処理はシンプルです。
- `$` を解放する
- `jQuery` という名前だけを残す
つまり「$はもうjQueryのものではない」と宣言します。
内部的には、jQuery読み込み前に存在していた `$` の参照を復元しています。
そのため、先に読み込まれていたライブラリは壊れません。
実際の状態の変化
noConflict前:
- `$` → jQuery
- `jQuery` → jQuery
noConflict後:
- `$` → 元のライブラリ
- `jQuery` → jQuery
この状態が、WordPressの標準です。
WordPressが必ずnoConflictを使う理由
WordPressは、テーマとプラグインが自由に追加されるCMSです。
つまり、どのJavaScriptライブラリが読み込まれるか事前に分かりません。
もし `$` をjQueryが占有したままだと、次のような問題が起きます。
- プラグイン同士の破壊
- 管理画面のUI停止
- 外部ウィジェットの不具合
そこでWordPressは、安全側に倒します。
常にnoConflict状態のjQueryを提供するのです。
これにより、他ライブラリは `$` を自由に使用できます。
ではどうやってjQueryを書くのか
WordPressでは、次の書き方が基本になります。
jQuery(function($){ $('.button').on('click', function(){ $('.panel').toggleClass('open'); }); });
この `$` は「引数として渡されたローカル変数」です。
グローバルの `$` とは別物です。
ここが重要です。
WordPressでは `$` を使えないのではなく、グローバル `$` を使ってはいけないのです。
よくある誤解
1. jQueryが壊れていると思う
多くの人は `$ is not a function` を見て、jQueryが壊れたと考えます。
しかし実際には、jQueryは正常に動作しています。
問題は「参照している変数」です。
2. CDN版にすれば直る
CDNのjQueryを読み込むと一時的に直ることがあります。
しかしそれは `$` を上書きしただけです。
プラグインが別のライブラリを使っている場合、今度はそちらが壊れます。
3. `$` を使えないのは不便
実際には使えます。
ただしスコープを限定する必要があります。
(function($){ $('.menu').show(); })(jQuery);
これは即時関数でローカル `$` を作っています。
WordPressテーマではこの書き方がよく使われます。
なぜこの設計が重要なのか
この仕組みは単なる互換性対策ではありません。
大規模システムにおける「名前空間」の問題です。
JavaScriptには本来、強い名前空間がありません。
そのため、グローバル変数は共有資源になります。
WordPressは、jQueryをnoConflictにすることで次のことを実現しています。
- テーマはjQueryを使える
- プラグインもjQueryを使える
- 他ライブラリも使える
つまり、衝突しない共存環境を作っています。
注意点:最も危険なコード
次のコードは特に危険です。
<script> $('.slider').slick(); </script>
HTML直書きのインラインスクリプトです。
WordPressの読み込み順に依存するため、タイミングによって動いたり止まったりします。
必ずenqueueしたスクリプトファイル内で、jQueryラッパーを使用するべきです。
まとめ
`noConflict()`は制限ではありません。
むしろ、複数のJavaScriptが共存するための安全装置です。
`$` が使えないのではなく、グローバル `$` を使わない設計になっています。
そしてこれを理解すると、原因不明の「ボタンが効かない」「スライダーが動かない」といった不具合の理由が見えてきます。
jQueryのトラブルの多くはライブラリの問題ではありません。
変数スコープを理解していないコードが原因です。
そしてWordPressでは、それが最も表面化しやすいのです。