views:

81

answers:

2

I have run into this jquery plugin and i quite understand how this works:

$.functionone = function(){

    function setOptions(newOptions){
        ...
    }
    this.setOptions = setOptions;
}

What i dont understand is what does this actually do? this.setOptions = setOptions can you call a function without parenthesis? What is the relationship between this.setOptions and setOptions by itself?

+1  A: 

The function setOptions is only called if you add parenthesis: setOptions(). If you do not add parenthesis, you have a reference to a function. This is just like a normal variable, only it contains a function reference instead of some other value.

If you set this.setOptions = setOptions, you make a function setOptions on the this object, which points to the same function as setOptions. That is, if you call it using this.setOptions(), the referenced function will be called.

Sjoerd
Hey, in this context though, i dont quite understand the 'this' in the code, cant you already just call the method $('div').functionone.setOptions()? is it's purpose only apply internally within the class?
anthonypliu
Without context, it is not clear what `this` points to. It does not have to point to the current class. It probably points to the div, as you indicated by $('div'). So this code adds a setOptions method to the diff, so that you can do $('div').setOptions(). You can not do $('div').functionone.setOptions(), you can not call a function within a function like that.
Sjoerd
+7  A: 

Functions in JavaScript are objects like (nearly) everything else. When you do this:

this.setOptions = setOptions;

you're not calling the setOptions function, you're just assigning a reference to the function to a property, exactly like setting a property to any other object, like this:

var dt;
dt = new Date();
this.today = dt;

With functions, you'd do this so you can later call the function via the property (which sets up the this value to be the object the property's on, which is handy). It's a bit clearer what's going on if you use a different name for the property than for the function:

function functionName() { ... }   // Declares the function
this.propertyName = functionName; // Sets the property
functionName();                   // Calls the function (with `this` = the global object ["window", on browsers])
this.propertyName();              // Also calls the function (but with `this` = the object the property's on)

The pattern you identified, declaring a function and then separately setting a reference to it on an object, is frequently used to make sure the resulting function has a name. You can create a function and bind it to a property like this:

this.setOptions = function() {
    ...
};

...but then the function doesn't have a name (the property does, but not the function), which can be an issue when you're trying to debug because debuggers show you the names of functions in various contexts (call stacks, for instance). If a lot of your functions don't have names, even though the properties referring to them do, it makes debugging difficult. More about anonymous vs. named functions here. (There's also a difference in terms of when the function is instantiated, but going into it here would just complicate things.)

You'd think you could combine things, like this:

this.setOptions = function setOptions() {  // <=== DON'T DO THIS
    ...
};

...but although that mostly works, it triggers a bug in Internet Explorer / JScript (it creates two different functions for that code, which is at best a memory waste and at worst a very subtle and time-wasting problem, as it was in this question).

T.J. Crowder