Core: deprecate jQuery.proxy (not slated for removal)

Fixes gh-2958
Close gh-3885
This commit is contained in:
Timmy Willison 2017-12-11 12:58:35 -05:00
parent 909e0c9925
commit 3a8e44745c
No known key found for this signature in database
GPG Key ID: 5F0C8B73EF56CE6F
6 changed files with 91 additions and 87 deletions

View File

@ -395,35 +395,6 @@ jQuery.extend( {
// A global GUID counter for objects
guid: 1,
// Bind a function to a context, optionally partially applying any
// arguments.
proxy: function( fn, context ) {
var tmp, args, 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 ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// Simulated bind
args = slice.call( arguments, 2 );
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
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
return proxy;
},
// jQuery.support is not used in Core but other projects attach their
// properties to it so it needs to exist.
support: support

View File

@ -2,8 +2,9 @@ define( [
"./core",
"./core/nodeName",
"./core/camelCase",
"./var/isWindow"
], function( jQuery, nodeName, camelCase, isWindow ) {
"./var/isWindow",
"./var/slice"
], function( jQuery, nodeName, camelCase, isWindow, slice ) {
"use strict";
@ -28,6 +29,37 @@ jQuery.fn.extend( {
}
} );
// Bind a function to a context, optionally partially applying any
// arguments.
// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
// However, it is not slated for removal any time soon
jQuery.proxy = function( fn, context ) {
var tmp, args, 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 ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// Simulated bind
args = slice.call( arguments, 2 );
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
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
return proxy;
};
jQuery.holdReady = function( hold ) {
if ( hold ) {
jQuery.readyWait++;

2
src/effects.js vendored
View File

@ -387,7 +387,7 @@ function Animation( elem, properties, options ) {
if ( result ) {
if ( jQuery.isFunction( result.stop ) ) {
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
jQuery.proxy( result.stop, result );
result.stop.bind( result );
}
return result;
}

View File

@ -1531,54 +1531,6 @@ QUnit.test( "jQuery.isEmptyObject", function( assert ) {
// equal(true, jQuery.isEmptyObject(null), "isEmptyObject on null" );
} );
QUnit.test( "jQuery.proxy", function( assert ) {
assert.expect( 9 );
var test2, test3, test4, fn, cb,
test = function() {
assert.equal( this, thisObject, "Make sure that scope is set properly." );
},
thisObject = { foo: "bar", method: test };
// Make sure normal works
test.call( thisObject );
// Basic scoping
jQuery.proxy( test, thisObject )();
// Another take on it
jQuery.proxy( thisObject, "method" )();
// Make sure it doesn't freak out
assert.equal( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." );
// Partial application
test2 = function( a ) {
assert.equal( a, "pre-applied", "Ensure arguments can be pre-applied." );
};
jQuery.proxy( test2, null, "pre-applied" )();
// Partial application w/ normal arguments
test3 = function( a, b ) {
assert.equal( b, "normal", "Ensure arguments can be pre-applied and passed as usual." );
};
jQuery.proxy( test3, null, "pre-applied" )( "normal" );
// Test old syntax
test4 = { "meth": function( a ) {
assert.equal( a, "boom", "Ensure old syntax works." );
} };
jQuery.proxy( test4, "meth" )( "boom" );
// jQuery 1.9 improved currying with `this` object
fn = function() {
assert.equal( Array.prototype.join.call( arguments, "," ), "arg1,arg2,arg3", "args passed" );
assert.equal( this.foo, "bar", "this-object passed" );
};
cb = jQuery.proxy( fn, null, "arg1", "arg2" );
cb.call( thisObject, "arg3" );
} );
QUnit.test( "jQuery.parseHTML", function( assert ) {
assert.expect( 23 );

View File

@ -208,3 +208,51 @@ QUnit.test( "jQuery.now", function( assert ) {
assert.ok( typeof jQuery.now() === "number", "jQuery.now is a function" );
} );
QUnit.test( "jQuery.proxy", function( assert ) {
assert.expect( 9 );
var test2, test3, test4, fn, cb,
test = function() {
assert.equal( this, thisObject, "Make sure that scope is set properly." );
},
thisObject = { foo: "bar", method: test };
// Make sure normal works
test.call( thisObject );
// Basic scoping
jQuery.proxy( test, thisObject )();
// Another take on it
jQuery.proxy( thisObject, "method" )();
// Make sure it doesn't freak out
assert.equal( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." );
// Partial application
test2 = function( a ) {
assert.equal( a, "pre-applied", "Ensure arguments can be pre-applied." );
};
jQuery.proxy( test2, null, "pre-applied" )();
// Partial application w/ normal arguments
test3 = function( a, b ) {
assert.equal( b, "normal", "Ensure arguments can be pre-applied and passed as usual." );
};
jQuery.proxy( test3, null, "pre-applied" )( "normal" );
// Test old syntax
test4 = { "meth": function( a ) {
assert.equal( a, "boom", "Ensure old syntax works." );
} };
jQuery.proxy( test4, "meth" )( "boom" );
// jQuery 1.9 improved currying with `this` object
fn = function() {
assert.equal( Array.prototype.join.call( arguments, "," ), "arg1,arg2,arg3", "args passed" );
assert.equal( this.foo, "bar", "this-object passed" );
};
cb = jQuery.proxy( fn, null, "arg1", "arg2" );
cb.call( thisObject, "arg3" );
} );

View File

@ -694,8 +694,8 @@ QUnit.test( "on(), with different this object", function( assert ) {
};
jQuery( "#firstp" )
.on( "click", jQuery.proxy( handler1, thisObject ) ).trigger( "click" ).off( "click", handler1 )
.on( "click", data, jQuery.proxy( handler2, thisObject ) ).trigger( "click" ).off( "click", handler2 );
.on( "click", handler1.bind( thisObject ) ).trigger( "click" ).off( "click", handler1 )
.on( "click", data, handler2.bind( thisObject ) ).trigger( "click" ).off( "click", handler2 );
assert.ok( !jQuery._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using different this object and data." );
} );
@ -1640,18 +1640,19 @@ QUnit.test( ".on()/.off()", function( assert ) {
jQuery( "#body" ).off( "click", "#foo" );
// Test binding with different this object
jQuery( "#body" ).on( "click", "#foo", jQuery.proxy( function() {
assert.equal( this.foo, "bar", "on with event scope" ); }, { "foo": "bar" }
) );
jQuery( "#body" ).on( "click", "#foo", function() {
assert.equal( this.foo, "bar", "on with event scope" );
}.bind( { "foo": "bar" } ) );
jQuery( "#foo" ).trigger( "click" );
jQuery( "#body" ).off( "click", "#foo" );
// Test binding with different this object, event data, and trigger data
jQuery( "#body" ).on( "click", "#foo", true, jQuery.proxy( function( e, data ) {
jQuery( "#body" ).on( "click", "#foo", true, function( e, data ) {
assert.equal( e.data, true, "on with with different this object, event data, and trigger data" );
assert.equal( this.foo, "bar", "on with with different this object, event data, and trigger data" );
assert.equal( data, true, "on with with different this object, event data, and trigger data" );
}, { "foo": "bar" } ) );
}.bind( { "foo": "bar" } ) );
jQuery( "#foo" ).trigger( "click", true );
jQuery( "#body" ).off( "click", "#foo" );