-1

I am having trouble with rewriting .proxy in jquery to Function.prototype.bind because .bind does not set guid on the bound function instances so that proxied event handlers can be removed without storing the instance of the proxied function.

If I replace .proxy with .bind, most scripts do not work anymore because of the missing guid being set.

How do I replace them to get rid of the deprecated messages and still have the scripts correctly working?

Below are some code lines of various JS scripts which do not work anymore when replaced with, for example, this.start.bind(this);.

Since .proxy does something significant different, I wonder why it is deprecated and moreover I wonder why in jQuery 4.0 the deprecated message appears as it was deprecated since jQuery 3.3 in 2018.

api.$element.on(this.eventType('start'), $.proxy(this.start, this));
api.$element.find('a').on(this.eventType('start'), function(e) {
    this.timeStamp = e.timeStamp;
}).on('click', function(e) {
    if (e.timeStamp - this.timeStamp > 400) {
        e.preventDefault(); // prevent Click
    }
});
$(document)
    .on(this.eventType('move'), $.proxy(this.move, this))
    .on(this.eventType('end'), $.proxy(this.end, this));
singleTapTimeout = setTimeout($.proxy(function() {
  doubleTapStartTime=null;
  //Trigger the event
  $element.trigger('tap', [event.target]);
  //Fire the callback
  if(options.tap) {
    ret = options.tap.call($element, event, event.target);
  }
}, this), options.doubleTapThreshold );
3
  • $.proxy does about the same thing, that bind does in vanilla JS, I think? Commented Dec 12 at 10:45
  • Yes, even api.jquery.com/jQuery.proxy says so: "Note: This API has been deprecated in jQuery 3.3; please use the native Function.prototype.bind method instead." Commented Dec 12 at 10:47
  • 1
    github.com/jquery/jquery/issues/2958#issuecomment-211433159 mentions that $.proxy does a tiny bit more though, "One thing that jQuery.proxy does and Function#bind doesn't is setting guid on the bound function instances so that proxied event handlers can be removed without storing the instance of the proxied function." - whether that's in any way relevant for your use case, you'll have to test I suppose. Commented Dec 12 at 10:48

2 Answers 2

2

The documentation for .proxy() lists the relacement:

Note: This API has been deprecated in jQuery 3.3; please use the native Function.prototype.bind method instead.

The jQuery code:

boundFunction = $.proxy(fn, context)

is equivalent to the native code:

boundFunction = fn.bind(context);

function fn() {
  return this.myData;
}

const context = { myData: "hello world" }

const bountWithjQuery = $.proxy(fn, context);
const bountNatively = fn.bind(context);

console.log(bountWithjQuery());
console.log(bountNatively());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>


Note: $.proxy() has additional effects when unbinding an event handler. From the documentation:

Be aware, however, that jQuery's event binding subsystem assigns a unique id to each event handling function in order to track it when it is used to specify the function to be unbound. The function represented by jQuery.proxy() is seen as a single function by the event subsystem, even when it is used to bind different contexts.

So, you lose this benefit with .bind(). The following code jQuery code will no longer work:

// add event handler
$(document).on("click", $.proxy(fn, context));

// remove event handler
$(document).off("click", fn);

The documentation continues with the recommendation:

To avoid unbinding the wrong handler, use a unique event namespace for binding and unbinding (e.g., "click.myproxy1") rather than specifying the proxied function during unbinding.

So, if you need to add and remove event bindings use event namespaces

// add event handler
$(document).on("click.myproxy1", fn.bind(context));

// remove event handler
$(document).off("click.myproxy1");
Sign up to request clarification or add additional context in comments.

1 Comment

If off/unbind is not used/needed, this should be sufficient I believe. I moved far away from jQuery since ES5/6 api.$element.on(this.eventType('start'), this.start.bind(this));
2

as mplunqjan says this works.

api.$element.on(this.eventType('start'), this.start.bind(this));

----------------------Solution added below ----------------
The resolve this i created a alternate proxy function with a different name and replaced .proxy calls with .alternate_proxy calls. The above provided solutions had side effects or made scripts not work as they guid is not set to a unique id. Rewriting all these scripts is too much time consuming. It was easier for me to recreate a similar .proxy function.

        jQuery.alternate_proxy = function( fn, context ) {
             "use strict";
            var tmp, args, alternate_proxy;

            if ( typeof context === "string" ) {
                tmp = fn[ context ];
                context = fn;
                fn = tmp;
            }

            // Quick check to determine if target is callable, in the spec
            // this throws a TypeError, but we will just return undefined.
            if ( typeof fn !== "function" ) {
                return undefined;
            }

            // Simulated bind
            args = [].slice.call( arguments, 2 );
            alternate_proxy = function() {
                return fn.apply( context || this, args.concat( [].slice.call( arguments ) ) );
            };

            // Set the guid of unique handler to the same of original handler, so it can be removed
            alternate_proxy.guid = fn.guid = fn.guid || jQuery.guid++;

            return alternate_proxy;
        };

2 Comments

This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - From Review
At Ruli I am sorry but I don't understand what you are saying. What do i have to do to get this reopened? I am missing the point. Thank you for your patience. The solution is provided above.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.