The jQuery.proxy() utility returns a new function that always runs with a chosen this value. This tutorial covers both API signatures, the official jQuery event-handler demos, partial argument binding, comparisons with Function.prototype.bind(), and safe unbinding patterns.
01
Syntax
$.proxy(fn, ctx)
02
By name
$.proxy(obj, "m")
03
Fixed this
Context locked
04
Extra args
Since jQuery 1.6
05
Events
Handler binding
06
bind()
Modern replacement
Fundamentals
Introduction
In JavaScript, this inside a function depends on how the function is called — not where it was written. That trips up beginners attaching object methods as click handlers: this becomes the clicked element instead of your object.
jQuery introduced jQuery.proxy() (also written $.proxy()) in version 1.4 to solve this. It wraps a function so it always executes with the context you choose. The API was deprecated in jQuery 3.3 in favor of native Function.prototype.bind(), but you will still encounter $.proxy in legacy plugins and tutorials.
Concept
Understanding the jQuery.proxy() Method
jQuery.proxy() does not run your function immediately — it returns a new wrapper function. When that wrapper is invoked (by a click, timer, or direct call), the original function runs with this locked to the context you supplied.
jQuery also tracks the link between the wrapper and the original function for event unbinding. That convenience comes with a caveat: multiple proxies of the same function can look identical to jQuery’s event subsystem, so use namespaced events when removing handlers.
💡
Beginner Tip
Think of $.proxy(obj.sayHi, obj) as “call sayHi later, but pretend it is always invoked as obj.sayHi().”
Foundation
📝 Syntax
jQuery.proxy supports two primary forms (plus optional extra arguments since 1.6):
you.test this.type = element
you.test this.type = person
me.test this.type = zombie
How It Works
Without proxy, passing you.test to .on("click", you.test) sets this to the clicked DOM element. $.proxy(you.test, you) wraps the method so this is always the you object.
📈 Practical Patterns
Method-by-name binding, partial arguments, native bind, and safe unbinding.
Example 2 — Official Demo: context, name Signature
Reference a method by string name on the context object — handy when the method lives on obj.
jQuery
var obj = {
name: "John",
test: function () {
return this.name;
}
};
var bound = $.proxy(obj, "test");
console.log(bound()); // "John"
$.proxy(obj, "test") is equivalent to $.proxy(obj.test, obj). The string form reads cleanly in plugin code that stores handler names in configuration objects.
Example 3 — Pre-Fill Arguments (Since jQuery 1.6)
Pass extra values that appear before the event object when the handler runs — from the official third demo.
jQuery
var me = {
type: "dog",
test: function (one, two, event) {
return "Hello " + one.type + ": I am a " + this.type +
", and they are " + two.type + ".";
}
};
var you = { type: "cat" };
var they = { type: "fish" };
var proxy = $.proxy(me.test, me, you, they);
// When called, you and they are args 1 and 2; event would be arg 3
console.log(proxy({ type: "click" }));
Arguments after context in $.proxy are fixed at bind time. jQuery forwards the event (and any caller args) after those pre-filled values — partial application without changing this.
Example 4 — Modern Equivalent with Function.prototype.bind()
Native bind covers the same use case in code written today.
jQuery
var widget = {
label: "Save",
handleClick: function () {
return "Clicked: " + this.label;
}
};
var withProxy = $.proxy(widget.handleClick, widget);
var withBind = widget.handleClick.bind(widget);
console.log(withProxy()); // Clicked: Save
console.log(withBind()); // Clicked: Save
For new projects, prefer fn.bind(context) or arrow functions. Choose $.proxy when maintaining jQuery 1.x–3.x code that relies on jQuery’s unbind tracking or when reading legacy plugin source.
Example 5 — Bind and Unbind with an Event Namespace
Avoid the proxy unbinding gotcha by namespacing events instead of passing the wrapper to .off(fn).
jQuery
var app = {
count: 0,
tick: function () {
this.count++;
return this.count;
}
};
var handler = $.proxy(app.tick, app);
// Bind with a unique namespace
$("#btn").on("click.myTick", handler);
// Later — remove by namespace, not by proxy reference
$("#btn").off("click.myTick");
console.log("Handler removed safely");
jQuery assigns one internal id per proxied wrapper. Multiple $.proxy(sameFn, differentCtx) bindings can interfere with each other during .off(handler). Namespaces like click.myTick target exactly the handler you attached.
Applications
🚀 Common Use Cases
Event handlers — keep this pointing at your widget/controller object on clicks and keyboard events.
Plugin methods — pass $.proxy(options.onComplete, instance) into jQuery APIs that invoke callbacks later.
Timers — bind setInterval / setTimeout callbacks to the correct object context.
Method-by-name config — use $.proxy(ctx, "handleSubmit") when handler names come from strings.
Partial application — pre-fill leading arguments before the event object arrives.
Legacy maintenance — read and refactor older jQuery codebases that predated widespread bind() usage.
🧠 How jQuery.proxy() Creates a Wrapper
1
Resolve function
Use the function argument directly, or look up context[name] for the string form.
Lookup
2
Capture context
Store the object that will become this when the wrapper runs.
Bind
3
Return wrapper
The wrapper calls the original function with fixed this and merged arguments.
Wrap
4
🔗
Invoke anywhere
Pass the wrapper to .on(), timers, or other APIs — context stays locked.
Important
📝 Notes
Available since jQuery 1.4; additional-argument form since 1.6; deprecated in jQuery 3.3.
Since jQuery 1.9, when context is null or undefined, the proxied function uses the same this as the proxy call — useful for partial application only.
Prefer Function.prototype.bind() in new code unless you need jQuery’s legacy unbind behavior.
Use event namespaces (click.myHandler) when unbinding proxied handlers.
Arrow functions capture lexical this but cannot serve as constructors and behave differently with arguments.
Does not copy the function — it wraps the original; changes to obj.method after proxying still affect calls.
Compatibility
Browser Support
jQuery.proxy() ships with jQuery since 1.4+ but is deprecated in 3.3. Native Function.prototype.bind() is supported in all modern browsers (IE9+) and is the recommended replacement.
✓ Deprecated · jQuery 3.3
jQuery jQuery.proxy()
Works in jQuery 1.x–3.x. Use fn.bind(context) in modern code. bind() is native ES5 — Chrome, Firefox, Safari, Edge, IE9+, and Node all support it.
100%Native bind() support
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
Function.prototype.bind()Universal
Bottom line: Learn $.proxy() to maintain legacy jQuery plugins. Write new handlers with method.bind(obj), arrow functions, or class fields depending on your style guide.
Wrap Up
Conclusion
The jQuery.proxy() utility solves the classic JavaScript problem of lost this context when passing object methods as callbacks. It returns a wrapper that always executes with the context you specify — ideal for jQuery event handlers in older code.
Modern projects should reach for Function.prototype.bind() or arrow functions instead. When you encounter $.proxy in the wild, remember namespaced events for clean unbinding.
Store the proxy reference if you need to remove one specific handler
Pre-fill args with the 1.6+ signature when it simplifies handlers
❌ Don’t
Pass raw obj.method to .on() expecting this === obj
Bind multiple proxies of the same fn without unique namespaces
Use $.proxy in greenfield code when bind() suffices
Forget that proxy returns a new function — it does not call immediately
Assume arrow functions and proxy solve problems the same way in all cases
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about jQuery.proxy()
Control this when functions become callbacks.
5
Core concepts
🔗01
$.proxy
Fixes this
API
📝02
Two forms
fn+ctx / ctx+name
Syntax
🚀03
Events
Handler binding
Main use
⚠04
Namespaces
Safe .off()
Gotcha
🔄05
bind()
Modern path
Migrate
❓ Frequently Asked Questions
jQuery.proxy() takes a function and returns a new function that always runs with a fixed this context. It is most useful for attaching object methods as event handlers so this inside the handler refers to your object, not the DOM element that triggered the event.
jQuery.proxy(function, context) wraps a function reference with a chosen this value. jQuery.proxy(context, "methodName") looks up a method on an object by name and returns a bound version. Since jQuery 1.6 you can pass additional arguments that are prepended to the call.
Both fix this and optionally pre-fill arguments. Native bind() is the modern standard. jQuery.proxy() was deprecated in 3.3 but adds jQuery-specific event tracking so .off() can still match the original function when unbinding — use unique event namespaces when multiple proxied handlers share one wrapper.
When you pass obj.handleClick directly to .on("click", obj.handleClick), JavaScript calls handleClick with this set to the clicked element. $.proxy(obj.handleClick, obj) returns a wrapper where this is always obj, no matter who invokes the function.
Not for new code. jQuery deprecated $.proxy() in version 3.3 in favor of fn.bind(context). Use method.bind(obj) or arrow functions when you do not need jQuery's legacy unbind tracking.
jQuery's event system treats each proxied wrapper as one function identity. If you bind $.proxy(fn, ctxA) and $.proxy(fn, ctxB), passing either proxy to .off() may remove both. Prefer namespaced events like .on("click.myHandler1", proxy) and .off("click.myHandler1") instead of relying on the function reference alone.
Did you know?
jQuery’s event subsystem tracks proxied functions so .off(originalFn) can still remove a handler bound with $.proxy(originalFn, ctx) — even though the wrapper is a different function object. That is why jQuery maintained $.proxy long after native bind() existed, and why namespaced unbinding remains the safest pattern when multiple proxies share one source function.