I think that I understand the difference between:

document.addEventListener('DOMContentLoaded', callback_fn);

and:

window.addEventListener('load', (event) => { ... });

However, as a jQuery user, what is the difference between DOMContentLoaded and the jQuery ready fn?

jQuery's ready() works asynchronously, even if the DOM is already ready, which keeps your code running consistently. jQuery simulates the non-existent DOMContentLoaded event on obsolete browsers like Internet Explorer, using deferred execution, that fires later than the real event in other browsers, making sure it doesn't run too early.

DOMContentLoaded event fires synchronously, when the initial HTML document has been completely loaded and parsed. It signifies that the DOM tree is ready for manipulations. It triggers as soon as the CSS, scripts are available, even before resources likes images or stylesheets finish loading. Most browsers support this.

In the past, ready() introduced a small delay. jQuery keeps consistent behavior across browsers. One is asynchronous, the other is synchronous.

<!DOCTYPE html>
<html>
<head>
    <title>Page Loading Benchmark</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        function benchmarkJQueryReady() {
            var startTime = performance.now();
            $(document).ready(function() {
                var endTime = performance.now();
                var loadTime = endTime - startTime;
                console.log('jQuery .ready(): Page loaded in ' + loadTime.toFixed(2) + ' milliseconds');
            });
        }
    </script>
</head>
<body onload="benchmarkJQueryReady()">
    <h1>Welcome to My Benchmark Page</h1>
    <p>This page measures the time it takes for the jQuery .ready() event to fire.</p>
    <a href="/my-url">Click here for a link</a>
</body>
</html>




<!DOCTYPE html>
<html>
<head>
    <title>Page Loading Benchmark</title>
    <script>
        function benchmarkDomContentLoaded() {
            var startTime = performance.now();
            document.addEventListener('DOMContentLoaded', function() {
                var endTime = performance.now();
                var loadTime = endTime - startTime;
                console.log('DOMContentLoaded: Page loaded in ' + loadTime.toFixed(2) + ' milliseconds');
            });
        }
    </script>
</head>
<body onload="benchmarkDomContentLoaded()">
    <h1>Welcome to My Benchmark Page</h1>
    <p>This page measures the time it takes for the DOMContentLoaded event to fire.</p>
    <a href="/my-url">Click here for a link</a>
</body>
</html>

However, as a jQuery user, what is the difference between DOMContentLoaded and the jQuery ready fn?

No difference really, although some sources state that the ready function might fire "a little" later (because it is wrapper code).

Of course I agree with toneewa and pritaeas but because it is an intresting topic I thought to share some thoughts to it.
Given the fact that I load jQuery (in one minified file that contains also every JavaScript that this part of the app requires) I load it dynamically after DOMContentLoaded or onLoad in older browsers. e.g.:

        var _fncl=false//if the loader function has called
        ,_fnc=function() // the loader function 
        { 
            _fncl=true;
            //I load here the minified JavaScript file that contains jQuery
        };
        window.addEventListener("DOMContentLoaded", _fnc);
        window.onload=function() // for browsers that don't support DOMContentLoaded
        {
            if(!_fncl) // if the loader function has not been called 
            {   
                _fnc(); 
            }
        };

And pretty much this is what jQuery also does in its core logic. I copy from https://code.jquery.com/jquery-3.7.1.js this part:

// The ready event handler and self cleanup method
function completed() {
    document.removeEventListener( "DOMContentLoaded", completed );
    window.removeEventListener( "load", completed );
    jQuery.ready();
}

// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
// Support: IE <=9 - 10 only
// Older IE sometimes signals "interactive" too soon
if ( document.readyState === "complete" ||
    ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

    // Handle it asynchronously to allow scripts the opportunity to delay ready
    window.setTimeout( jQuery.ready );

} else {

    // Use the handy event callback
    document.addEventListener( "DOMContentLoaded", completed );

    // A fallback to window.onload, that will always work
    window.addEventListener( "load", completed );
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.