Reputation: 105439
I have an object which has a method. This method can be triggered as method on object or as callback function. What is the best way to determine how it's called? I've come up with a solution that I'm not sure is relible.
function Object() {
this.method = function(elem) {
if (elem.type !== undefined) {
alert("we've got an event");
} else {
alert("it doens's seem to be an event");
}
}
}
var obj = new Object();
$('span').click(obj.method);
obj.method($('div'));
I've decided to edit my question a bit to point out that the question is not about 'this' parameter and how to bind function's context.
Upvotes: 0
Views: 198
Reputation: 105439
I think this option is even better: I remove the check from the method and always expect an element to be passed. As a callback I pass the function that takes 'this' which will be a reference to the element and passes to my method:
$('span').click(function(){obj.method(this)};
Upvotes: 0
Reputation: 4399
If you want to bind a function to a context (object), then use something like this:
function createOnClick(obj, fn) {
return function() {
return fn.apply(obj, arguments);
}
}
myObject = new Object();
$('button').click(createOnClick(myObject, myObject.method));
Now, when your method is called, 'this' will be a reference to the 'myObject' instance. This is commonly known and function binding and there are many API's that already do this. However, I am unfamiliar with JQuery, so you will need to refer to the documentation.
Upvotes: 0
Reputation: 754565
The best way to determine if this is a callback is to register a different function as the callback and explicitly pass down a value to say it was indeed a callback
function Object() {
this.method = function(elem, isCallback) {
if (isCallback) {
}
}
}
var obj = new Object();
$('span').click(function (elem) { obj.method(elem, isCallback); });
obj.method($('div'));
Upvotes: 0
Reputation: 114
This works. Pretty close to what you had.
function Object() {
this.method = function(elem) {
console.log(elem)
if (elem.length != 0 && elem instanceof jQuery.Event) {
alert("Accessed on Click");
} else {
alert("Not accessed on click.");
}
}
}
var obj = new Object();
$('span').click(obj.method); // Accessed on click.
obj.method($('div')); // Not accesed on click.
http://jsfiddle.net/dietrichg/3mELA/
Upvotes: 0
Reputation: 140210
You should just have 2 different methods if they do different things.
If you really have the method do the same thing regardless of if it's called
as a method or a callback, you can use $.proxy
so that this
is always the object:
function Object() {
this.method = $.proxy( function(){
}, this );
}
var obj = new Object();
Upvotes: 0
Reputation: 2127
If it's just about jQuery stuff (e.g. $.click), you could check if the event itself is passed to the function:
var handleClick = function () {
var $this = $(this); // obj
if (arguments.length > 0 && arguments[0] instanceof jQuery.Event) {
alert('called as callback');
} else {
alert('called directly');
}
};
$('button').click(handleClick);
handleClick();
Upvotes: 1
Reputation: 15397
I'm not sure why it should matter how the code was called. I bet that if you can articulate why it does matter, you'll see there's a parameter that should be passed to the function that lets the function know this. Then you could make a simple wrapper that will do it appropriately:
function MyObject() {
this.method = function(randomParam1, randomParam2, calledThroughAlert) {
// calledThroughAlert knows what you need to know.
}
}
function callbackToMyObject() {
obj.method('foo', 'bar', true);
}
var obj = new MyObject();
$('span').click(callbackToMyObject);
obj.method('bar', 'foo'); // defaults the calledThroughAlert param to false
Upvotes: 1
Reputation: 75307
The value of this
inside method
will be the Object
instance (see Rocket's comment about naming) for all intents and purposes (unless the value was purposefully set via bind()
, call()
or apply()
).
When executed as a method, the value of this
will be the Object
instance (again, unless altered via bind()
, call()
or apply()
).
function Object() {
var that = this;
this.method = function(elem) {
if (this !== that) {
alert("we've got an event");
} else {
alert("it doens's seem to be an event");
}
}
}
You can see this working here http://jsfiddle.net/5WzEA/.
Upvotes: 0