$ is not a function but jQuery is loaded when adding JavaScript to a custom theme
The Drupal js documentation states


  Note: Since Drupal uses jQuery.noConflict() and only loads JavaScript
  files when required, to use jQuery and the $ shortcode for jQuery you
  must include jQuery and Drupal as dependencies in the library
  definition in your MODULE.libraries.yml and add a wrapper around your
  function.


You should also use behaviors instead of document.ready() which is stated earlier in the above documentation. 


  However with Drupal there is an alternate better method [to document.ready()]; using the
  functionality of Drupal.behaviors and once(). If used properly this
  will ensure that your code runs both on normal page loads and when
  data is loaded by AJAX (or BigPipe!) - but not jQuery methods like
  load() which should be avoided as Drupal behaviors will fail to load
  for loading functions other than ajax().


So your snippet should look like:

(function ($, Drupal) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      $(window).once().on('load scroll', function () {
        // ...
      });
    }
  };
})(jQuery, Drupal);


If your selector is something other than window, e.g. a class, you should update it to be something like $('.my-class', context).once().etc. Passing context like this ensures that your js only fires if the element exists in the currently being loaded context, i.e. if a small chunk of the page is loaded via ajax context will only contain that small chunk of the page. .once() ensures the js will only be added to the element once. It will prevent scenarios where you single click an element but it acts as though you double or triple clicked it. Here is the documentation for .once().