Reputation: 398
I'm experimenting with having an object extended and that object containing multiple functions. I'm having trouble explaining it, so let me just show you my code. Let's start with what is working:
(function ($) {
$.fn.extend({
Hello: function() {
console.log("Well, hello back!");
console.log($(this));
}
});
})(jQuery);
In HTML:
<script>
$(document).ready(function() {
$('.target').Hello();
});
</script>
The console log of $(this) is giving me the callee element "target", as expected.
Now, let's try it this way:
(function ($) {
$.fn.extend({
Response: {
Hello: function() {
console.log("Well, hello back!");
console.log($(this));
}
}
});
})(jQuery);
In HTML:
<script>
$(document).ready(function() {
$('.target').Response.Hello();
});
</script>
This is still spitting out "Well, hello back!" in the console, but I'm no longer getting the callee when I use $(this). I'm instead getting the Hello function.
How do I get the callee? I've tried this.parent, which does not work. Please help!
Upvotes: 1
Views: 78
Reputation: 1244
As others have pointed out, you can't really do what you are asking for, but you can do something that looks almost the same.
By capturing 'this' with a closure, you can access it further down in your object structure:
$.fn.extend({
Response: function () {
var self = this;
return {
Hello: function () {
console.log(self);
}
};
}
});
$('.target').Response().Hello();
Upvotes: 1
Reputation: 4295
Unfortunately, there is no parent-child relationship between objects in JavaScript. The reason for this is that it is possible for the same object to have multiple parents. This can be difficult to grasp when you are dealing with nested objects (as is the case in the code example you have provided). Consider the following example:
var foo = {
bar: {
baz: 1,
biz: function() { console.log(this) }
}
}
foo.bar.biz();
=> { baz: 1, biz: [Function] }
var y = {};
y.foobar = foo.bar
y.foobar.biz();
=> { baz: 1, biz: [Function] }
In both cases, a call to biz
will return only the immediately containing object. To attempt to access the parent of the bar
object through the this
keyword would be ambiguous because there are multiple parents that have been specified.
In your case, your best option would be to use the call
function to explicitly specify the function context:
var $target = $('.target');
$.fn.Response.Hello.call($target);
Upvotes: 0
Reputation: 437336
You can't really do that -- it's quite impractical.
There are special rules in JavaScript that dictate what the value of this
is when a function is called. One of them is that whenever there is an expression of the form foo.bar()
then bar
is called and this
evaluates to foo
for the call.
So when you are run $('.target').Response.Hello()
what happens is that this
is equal to $.fn.Response
, and not the jQuery object that wraps .target
.
You could get the desired behavior by overriding the assignment of this
by using e.g. Function.prototype.call
:
var $target = $('.target');
$target.Response.Hello.call($target);
Of course this is cumbersome, but there's not much choice. The only other solution that would theoretically work I can think of involves the idea of injecting code into jQuery so that $$.Response
resolves to something different for each jQuery instance $$
. This is probably overkill if the aim of the question is simply to achieve a preferred syntax.
Upvotes: 1