jQuery / noConflict() with Other Libraries and jQuery Versions

jQuery.noConflict() restores the global $ that existed before jQuery and returns the current jQuery function. Store it as jq to coexist with another library’s dollar. Passing true restores the previous global jQuery name too, but does not solve API or plugin compatibility.

Default versus true

jQuery.noConflict() restores references saved during initialization. Default releases $ while keeping jQuery. noConflict(true) restores both names. It does not create an earlier library if no previous value existed.

The return is the same function, not a cloned library. jq is an alias, usable as jq("selector") or jq.ajax(). Assigning global $ back to jQuery takes away the name again; prefer explicit local scope.

Complete example preserving another dollar owner

Save everything as UTF-8 noconflict-demo.html and open it in a browser. Internet loads the official jQuery file 4.0.0. No server or installation is needed. The first function is a mock owner, not an actual third-party library.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Return the global dollar alias</title>
  <script>
    // A mock owner, not a real third-party library.
    window.$ = function () { return "other library"; };
    window.previousDollar = window.$;
  </script>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <script>
    const jq = jQuery.noConflict();
    jq(function ($) {
      let clicks = 0;
      function report() {
        $("#result").text(`global dollar=${window.$()}\noriginal dollar restored=${window.$ === window.previousDollar}\nglobal jQuery kept=${window.jQuery === jq}\nlocal alias=${$ === jq}\nclicks=${clicks}`);
      }
      $("#add").on("click", function () { clicks++; report(); });
      $("#reset").on("click", function () { clicks = 0; report(); });
      report();
    });
  </script>
  <style>body { font: 16px/1.6 sans-serif; margin: 20px; } button { font: inherit; margin: 4px; } pre { white-space: pre-wrap; overflow-wrap: anywhere; }</style>
</head>
<body>
  <button type="button" id="add">Use local jQuery</button>
  <button type="button" id="reset">Reset counter</button>
  <pre id="result" aria-live="polite"></pre>
</body>
</html>

Initial output. Global $ is restored; global jQuery and the callback’s local $ use jQuery. This behavior was executed separately with 3.7.1 and 4.0.0 in Windows Edge.

global dollar=other library
original dollar restored=true
global jQuery kept=true
local alias=true
clicks=0
  1. Press Use local jQuery three times for clicks=3. Its handler uses local jQuery.
  2. global dollar remains other library and original dollar restored=true compares original function identity.
  3. Reset counter restores zero without reloading the library or page.

The DOM-ready callback jq(function ($) { ... }) receives the calling jQuery as its parameter. This local $ differs from window.$. Preserve that scope when moving code into another function. Arrow parameters can also receive the alias; event handlers needing this require separate care.

Complete example with two versions

Save the next complete file separately as two-versions-demo.html. Load 3.7.1 and retain legacy, then load 4.0.0 and immediately retain its noConflict(true) return as modern. Keep script order; do not add async to this exercise.

Prefer one jQuery version on a site. This diagnostic example explains ownership on existing mixed-version pages. lessonOnly is a tiny mock plugin, not a compatibility test of a real plugin.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Two jQuery instances with explicit owners</title>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <script>
    const legacy = jQuery;
    legacy.fn.lessonOnly = function () { return "legacy plugin"; };
  </script>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <script>
    const modern = jQuery.noConflict(true);
    modern(function ($) {
      let oldClicks = 0, newClicks = 0;
      const element = document.getElementById("shared");
      legacy(element).data("owner", "legacy");
      modern(element).data("owner", "modern");
      function report() {
        $("#result").text([
          "global jQuery=" + window.jQuery.fn.jquery,
          "global dollar=" + window.$.fn.jquery,
          "modern alias=" + modern.fn.jquery,
          "same function=" + (legacy === modern),
          "legacy plugin=" + legacy("#shared").lessonOnly(),
          "modern plugin=" + typeof modern.fn.lessonOnly,
          "shared data=" + legacy(element).data("owner") + "/" + modern(element).data("owner"),
          "legacy clicks=" + oldClicks + "; modern clicks=" + newClicks
        ].join("\n"));
      }
      legacy("#old").on("click", function () { oldClicks++; report(); });
      modern("#new").on("click", function () { newClicks++; report(); });
      modern("#reset").on("click", function () { oldClicks = newClicks = 0; report(); });
      report();
    });
  </script>
  <style>body { font: 16px/1.6 sans-serif; margin: 20px; } button { font: inherit; margin: 4px; } pre { white-space: pre-wrap; overflow-wrap: anywhere; }</style>
</head>
<body>
  <p id="shared">One DOM element, two instance-specific data stores.</p>
  <button type="button" id="old">Legacy handler</button>
  <button type="button" id="new">Modern handler</button>
  <button type="button" id="reset">Reset counters</button>
  <pre id="result" aria-live="polite"></pre>
</body>
</html>

Initial output was verified with both actual versions loaded together in Windows Edge.

global jQuery=3.7.1
global dollar=3.7.1
modern alias=4.0.0
same function=false
legacy plugin=legacy plugin
modern plugin=undefined
shared data=legacy/modern
legacy clicks=0; modern clicks=0
  1. Global jQuery and dollar return to 3.7.1; modern alias retains 4.0.0.
  2. Press Legacy handler once and Modern handler twice: legacy clicks=1; modern clicks=2.
  3. lessonOnly belongs only to legacy.fn, so modern plugin=undefined. The same DOM element’s owner data reads legacy/modern through the separate instances.
  4. Reset counters resets counts only, preserving names and loading order.

What separate names cannot fix

Both instances manipulate one document. Their plugin registrations and .data() stores differ, but DOM removal or attribute changes are shared. Track which instance registered events or owns cleanup. Aliases do not create separate pages.

A plugin reading global jQuery attaches to the instance available when it loads. After deep restoration it does not automatically attach to modern. Check every plugin’s supported versions and loading mechanism.

The official conflict guide places alias restoration immediately after loading. Use saved references consistently. For “$ is not a function,” inspect global values, jq.fn.jquery and plugin methods before adding noConflict blindly. Failed downloads and removed APIs are different causes.

In an environment such as WordPress that already manages dependencies, do not paste both demo CDN files into production. Inspect registered dependencies and existing local aliases first. During recovery, preserve plugin ownership rather than overwriting globals arbitrarily.