Taha Paksu Taha Paksu - 3 months ago 9
jQuery Question

jQuery set scope of method

I just wondered if something like this can be achieved:

Assume that I have a event callback inside my library defined:



var app = {
globals: {
foo: null
},
bar: function(e) {
e.preventDefault();
e.stopPropagation();
if (typeof app.globals.foo === "function") app.globals.foo(e);
},
init: function(options) {
$.extend(app.globals, options);
$(".myclass").on("click", function(e) {
app.bar(e);
});
}
};

$(document).ready(function() {
app.init({
foo: function(evt) {
alert("clicked");
console.log(evt.target);
}
});
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myclass">Click Me!</div>





With this method, I'm passing the ".myclass" elements' click event data to
app.foo
, so the object oriented method would be executed.

TL;DR: The question is, can I set the scope of foo as the object which sent the click event? So:

app.init({
foo: function(){
console.log(this);
}
});


would be executed same as:

app.init({
foo: function(evt){
console.log(evt.target);
}
});


Is something like this possible?

Answer

You can control the this value for the foo function on activation:

// ...
if(typeof app.globals.foo === "function") app.globals.foo.call(e.target);
// ...

Will set the this to be equal to e.target and you'll get the behavior you described, however...

It's not a good practice to do so. First, if foo is bound to a specific this (for example via foo.bind(someContext) this method will fail to override that context. Second, it's unnatural to have a this context when there's no real object context - that's what function arguments are used for. The "common exception" to this (often found in jQuery callbacks) is passing the context to an "isolated" callback function, not an "object method", and even then it's hard to justify this because of the same reason, function arguments are much clearer and less fragile.

Comments