diff --git a/core/.eslintrc.jquery.json b/core/.eslintrc.jquery.json
index dda0cf76f761325319eb21d971f4a46c9c668783..def86d7efff391f7f95e8f538c8f66774f77b288 100644
--- a/core/.eslintrc.jquery.json
+++ b/core/.eslintrc.jquery.json
@@ -37,7 +37,7 @@
     "jquery/no-parents": 0,
     "jquery/no-parse-html": 0,
     "jquery/no-prop": 0,
-    "jquery/no-proxy": 0,
+    "jquery/no-proxy": 2,
     "jquery/no-ready": 2,
     "jquery/no-serialize": 0,
     "jquery/no-show": 0,
diff --git a/core/misc/details-summarized-content.js b/core/misc/details-summarized-content.js
index 79f87cf321eb7d4bbcbc96a726864cd3f0272516..bef9400bd23dac6a8890a97920ca5a1a38aced10 100644
--- a/core/misc/details-summarized-content.js
+++ b/core/misc/details-summarized-content.js
@@ -44,7 +44,7 @@
           Drupal.theme('detailsSummarizedContentWrapper'),
         );
         this.$node
-          .on('summaryUpdated', $.proxy(this.onSummaryUpdated, this))
+          .on('summaryUpdated', this.onSummaryUpdated.bind(this))
           .trigger('summaryUpdated')
           .find('> summary')
           .append(this.$detailsSummarizedContentWrapper);
diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js
index df82b0af0d80d96684d0e1d1fb97123c8c581f3c..1f14dc12817d0eee5c4b72629919e44a99dd70a6 100644
--- a/core/misc/dropbutton/dropbutton.js
+++ b/core/misc/dropbutton/dropbutton.js
@@ -61,26 +61,26 @@
          *
          * @ignore
          */
-        'mouseleave.dropbutton': $.proxy(this.hoverOut, this),
+        'mouseleave.dropbutton': this.hoverOut.bind(this),
 
         /**
          * Clears timeout when mouseout of the dropdown.
          *
          * @ignore
          */
-        'mouseenter.dropbutton': $.proxy(this.hoverIn, this),
+        'mouseenter.dropbutton': this.hoverIn.bind(this),
 
         /**
          * Similar to mouseleave/mouseenter, but for keyboard navigation.
          *
          * @ignore
          */
-        'focusout.dropbutton': $.proxy(this.focusOut, this),
+        'focusout.dropbutton': this.focusOut.bind(this),
 
         /**
          * @ignore
          */
-        'focusin.dropbutton': $.proxy(this.focusIn, this),
+        'focusin.dropbutton': this.focusIn.bind(this),
       });
     } else {
       this.$dropbutton.addClass('dropbutton-single');
@@ -176,7 +176,7 @@
        */
       hoverOut() {
         // Wait half a second before closing.
-        this.timerID = window.setTimeout($.proxy(this, 'close'), 500);
+        this.timerID = window.setTimeout(this.close.bind(this), 500);
       },
 
       /**
diff --git a/core/misc/states.js b/core/misc/states.js
index 0c01f6a867bb930b66ae7970692adb20a37e6702..957349d9b941488206b35a919526e5d16faac727 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -477,7 +477,7 @@
       // Attach the event callback.
       this.element.on(
         event,
-        $.proxy(function (e) {
+        function (e) {
           const value = valueFn.call(this.element, e);
           // Only trigger the event if the value has actually changed.
           if (oldValue !== value) {
@@ -488,18 +488,18 @@
             });
             oldValue = value;
           }
-        }, this),
+        }.bind(this),
       );
 
       states.postponed.push(
-        $.proxy(function () {
+        function () {
           // Trigger the event once for initialization purposes.
           this.element.trigger({
             type: `state:${this.state}`,
             value: oldValue,
             oldValue: null,
           });
-        }, this),
+        }.bind(this),
       );
     },
   };
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index 47fa97a83da48ea745a7983cc3ddc794f48ea441..c50de1ff3b84310c0733b68d5ed00e1b153879f0 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -238,10 +238,10 @@
     );
     this.$toggleWeightButton.on(
       'click',
-      $.proxy(function (e) {
+      function (e) {
         e.preventDefault();
         this.toggleColumns();
-      }, this),
+      }.bind(this),
     );
     $table.before($toggleWeightWrapper);
 
@@ -267,7 +267,7 @@
     // React to localStorage event showing or hiding weight columns.
     $(window).on(
       'storage',
-      $.proxy(function (e) {
+      function (e) {
         // Only react to 'Drupal.tableDrag.showWeight' value change.
         if (e.originalEvent.key === 'Drupal.tableDrag.showWeight') {
           // This was changed in another window, get the new value for this
@@ -275,7 +275,7 @@
           showWeight = JSON.parse(e.originalEvent.newValue);
           this.displayColumns(showWeight);
         }
-      }, this),
+      }.bind(this),
     );
 
     // Check for any rows marked as changed before this tabledrag was rerendered
diff --git a/core/misc/tableresponsive.js b/core/misc/tableresponsive.js
index 840bbf0e8cb1367f35bbab5c9a1ed0e866335a66..39ad39bf72fe49267e794caadb03aac8d42e06f8 100644
--- a/core/misc/tableresponsive.js
+++ b/core/misc/tableresponsive.js
@@ -37,7 +37,7 @@
           'Show table cells that were hidden to make the table fit within a small screen.',
         ),
       )
-      .on('click', $.proxy(this, 'eventhandlerToggleColumns'));
+      .on('click', this.eventhandlerToggleColumns.bind(this));
 
     this.$table.before(
       $('<div class="tableresponsive-toggle-columns"></div>').append(
@@ -49,7 +49,7 @@
     $(window)
       .on(
         'resize.tableresponsive',
-        $.proxy(this, 'eventhandlerEvaluateColumnVisibility'),
+        this.eventhandlerEvaluateColumnVisibility.bind(this),
       )
       .trigger('resize.tableresponsive');
   }
diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js
index 8ad62d4dc96a36f54a26a988d05489d039bbfd73..5365ade4724c79bfe4a69de852f05e9147d663d8 100644
--- a/core/modules/views/js/ajax_view.js
+++ b/core/modules/views/js/ajax_view.js
@@ -107,7 +107,7 @@
       )}-${settings.view_display_id.replace(/_/g, '-')}`,
     );
     once('exposed-form', this.$exposed_form).forEach(
-      $.proxy(this.attachExposedFormAjax, this),
+      this.attachExposedFormAjax.bind(this),
     );
 
     // Add the ajax to pagers.
@@ -116,8 +116,8 @@
       this.$view
         // Don't attach to nested views. Doing so would attach multiple behaviors
         // to a given element.
-        .filter($.proxy(this.filterNestedViews, this)),
-    ).forEach($.proxy(this.attachPagerAjax, this));
+        .filter(this.filterNestedViews.bind(this)),
+    ).forEach(this.attachPagerAjax.bind(this));
 
     // Add a trigger to update this view specifically. In order to trigger a
     // refresh use the following code.
@@ -174,7 +174,7 @@
       .find(
         '.js-pager__items a, th.views-field a, .attachment .views-summary a',
       )
-      .each($.proxy(this.attachPagerLinkAjax, this));
+      .each(this.attachPagerLinkAjax.bind(this));
   };
 
   /**
diff --git a/core/modules/views_ui/js/views-admin.js b/core/modules/views_ui/js/views-admin.js
index d046d08a92b385d3b49b863ad7567c4cdd922e8d..2829de963208c025c331c38f7212a79996fe5a86 100644
--- a/core/modules/views_ui/js/views-admin.js
+++ b/core/modules/views_ui/js/views-admin.js
@@ -157,9 +157,7 @@
 
     // Create bound versions of this instance's object methods to use as event
     // handlers. This will let us easily unbind those specific handlers later
-    // on. NOTE: jQuery.proxy will not work for this because it assumes we want
-    // only one bound version of an object method, whereas we need one version
-    // per object instance.
+    // on.
     const self = this;
 
     /**
@@ -294,7 +292,7 @@
     this.$form = $form;
     this.$form
       .find('.views-filterable-options :checkbox')
-      .on('click', $.proxy(this.handleCheck, this));
+      .on('click', this.handleCheck.bind(this));
 
     /**
      * Find the wrapper of the displayed text.
@@ -498,7 +496,7 @@
     this.$form.on(
       'formUpdated',
       `${searchBoxSelector},${controlGroupSelector}`,
-      $.proxy(this.handleFilter, this),
+      this.handleFilter.bind(this),
     );
 
     this.$searchBox = this.$form.find(searchBoxSelector);
@@ -715,7 +713,7 @@
       ),
     ).on(
       'change.views-rearrange-filter-handler',
-      $.proxy(this, 'redrawOperatorLabels'),
+      this.redrawOperatorLabels.bind(this),
     );
 
     // Bind handlers so that when a "Remove" link is clicked, we:
@@ -732,11 +730,11 @@
     )
       .on(
         'click.views-rearrange-filter-handler',
-        $.proxy(this, 'updateRowspans'),
+        this.updateRowspans.bind(this),
       )
       .on(
         'click.views-rearrange-filter-handler',
-        $.proxy(this, 'redrawOperatorLabels'),
+        this.redrawOperatorLabels.bind(this),
       );
   };
 
@@ -764,7 +762,7 @@
           .find('#views-add-group-link')
           .on(
             'click.views-rearrange-filter-handler',
-            $.proxy(this, 'clickAddGroupButton'),
+            this.clickAddGroupButton.bind(this),
           );
 
         // Find each (visually hidden) button for removing a filter group and
@@ -788,7 +786,7 @@
           ).on(
             'click.views-rearrange-filter-handler',
             { buttonId },
-            $.proxy(this, 'clickRemoveGroupButton'),
+            this.clickRemoveGroupButton.bind(this),
           );
         }
       },
@@ -884,7 +882,7 @@
           return;
         }
 
-        this.dropdowns.on('change', $.proxy(this, 'operatorChangeHandler'));
+        this.dropdowns.on('change', this.operatorChangeHandler.bind(this));
       },
 
       /**
@@ -1214,7 +1212,7 @@
     this.$button.hide();
     this.$parent.find('.exposed-description, .grouped-description').hide();
 
-    this.$input.on('click', $.proxy(this, 'clickHandler'));
+    this.$input.on('click', this.clickHandler.bind(this));
   };
 
   /**