Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguity in interpreting optional parameters

The signature of the jQuery function .on is

$(elements).on(events [, selector] [, data], handler);

where selector and data are optional. Therefore, the function call

$(elements).on(var1, var2, var3);

could be interpreted with var2 as either selector or as data. Is there ambiguity?

More generally, how is ambiguity from optional parameters dealt with for any other jQuery function?

like image 854
Randomblue Avatar asked Nov 18 '11 21:11

Randomblue


4 Answers

If only one of the selector and data parameters is provided and the value is a string it is assumed to be a selector.

From the jQuery doco for .on():

The data argument can be any type, but if a string is used the selector must either be provided or explicitly passed as null so that the data is not mistaken for a selector. Best practice is to use an object (map) so that multiple values can be passed as properties.

A similar principle applies to other jQuery methods with optional parameters.

like image 171
nnnnnn Avatar answered Sep 21 '22 02:09

nnnnnn


Selector is a string and data an object. The test should be something like.

if (typeof var2 === 'string') {
   // var2 is selector
} else {
   // var2 is data
}

Edit, the actual jQuery source from https://github.com/jquery/jquery/blob/master/src/event.js

on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
    var origFn, type;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {
        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {
            // ( types-Object, data )
            data = selector;
            selector = undefined;
        }
        for ( type in types ) {
            this.on( type, selector, data, types[ type ], one );
        }
        return this;
    }
like image 44
12000 Avatar answered Sep 21 '22 02:09

12000


For the example you gave, the selector and data arguments expect different types of object. The selector argument should be a String, and data should be an Object. They can be differentiated between using the typeof operator. For example:

if(typeof selector === "string") {
    //We know that the 2nd argument is actually a selector string
}

Note that if you did need to pass a String into on as the data argument, the selector argument would have to be specified too (even if you just pass in null).

like image 30
James Allardice Avatar answered Sep 21 '22 02:09

James Allardice


Here's a bit of the jquery source. Basically, they're looking at the types of the parameters and assigning them to other parameters as needed. For example, if the item in the "selector" position in the parameter list is not a string, they assume it was meant to be the "data" parameter, and so forth.

on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
    var origFn, type;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {
        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {
            // ( types-Object, data )
            data = selector;
            selector = undefined;
        }
        for ( type in types ) {
            this.on( type, selector, data, types[ type ], one );
        }
        return this;
    }

    if ( data == null && fn == null ) {
        // ( types, fn )
        fn = selector;
        data = selector = undefined;
    } else if ( fn == null ) {
        if ( typeof selector === "string" ) {
            // ( types, selector, fn )
            fn = data;
            data = undefined;
        } else {
            // ( types, data, fn )
            fn = data;
            data = selector;
            selector = undefined;
        }
    }
like image 37
Jacob Mattison Avatar answered Sep 23 '22 02:09

Jacob Mattison