Can someone explain to me the importance of using function wrappers (ie: when assigning onclick functionality)? I know I should, but I don't fully understand why...
Example: It's my understanding that this:
$(callingImg)[0].setAttribute("onclick", "function(){removeChildren(this);}");
is better than this:
$(callingImg)[0].setAttribute("onclick", "removeChildren(this)");
One of the most common uses of function wrappers is to maintain or lock in that function's context. For example, if you have some object and you want to use one of it's method's as the onclick handler for a given element:
someElement.onclick = someObject.someMethod;
If someObject.someMethod makes any references to this, instead of this pointing to someObject it will instead point to someElement because the context has changed. By wrapping the someObject.someMethod
someElement.onclick = function() { someObject.someMethod() };
you are still executing someMethod as a method of someObject rather than as a method of someElement.
However, if the event handler method never makes any references to this, then a wrapper isn't needed.
From the example code that you posted, if you just did
$(callingImg)[0].setAttribute("onclick", removeChildren(this));
removeChildren(this) would be executed immediately and it's return value would be assigned as the onclick handler.
Here's some sample code to illustrate what's happening
var FakeElement = function() {
this.name = "FakeElement";
this.onclick = function() {};
};
var FakeEventHandler = function() {
this.name = "FakeHandlerObject";
this.clickHandler = function() {
console.log("`this` = ", this.name);
};
};
var e = new FakeElement();
var h = new FakeEventHandler();
// Normal usage, `this` points to instance of `h`
console.info("h.clickHandler();");
h.clickHandler();
// Context of this is changed to `e` instead of `h`
console.info("e.onclick = h.clickHandler;");
e.onclick = h.clickHandler;
e.onclick();
// Wrapped to maintain proper context of `this` within `h`
console.info("e.onclick = function() { h.clickHandler(); };");
e.onclick = function() { h.clickHandler(); };
e.onclick();
// Executed immediately and returns `null` causing an error in `e.onclick();`
console.info("e.onclick = h.clickHandler();");
e.onclick = h.clickHandler();
e.onclick();
Output:
h.clickHandler();
`this` = FakeHandlerObject
e.onclick = h.clickHandler;
`this` = FakeElement
e.onclick = function() { h.clickHandler(); };
`this` = FakeHandlerObject
e.onclick = h.clickHandler();
`this` = FakeHandlerObject
As a side note, it looks like you're using jQuery. If that's the case, you can simply do
$($(callingImg)[0]).click(function() {
removeChildren(this);
});
better still, if there is always one callingImg or you want to apply the same click handler to every callingImg, you can just do
$(callingImg).click(function() {
removeChildren(this);
});
They're generally used to limit variable scope and guaranteeing that you won't pollute your surrounding scope(s).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With