What is this pattern for (self = this)
In JavaScript, when you refer to a variable outside of the current function, you create a closure. Basically, you are guaranteeing that you will have access to a given variable, which in this case, happens to be the object that contains the method. As noted in the other answer, "this" is notoriously hard to pin down, a side effect of how JavaScript determines its scope.
However, notice how the framework inherently protects you from this behavior; the author of that code didn't need to specify "self", because setCallback actually sets "this" to the first parameter, which is typically "this." In plain JavaScript, you end up needing to use this trick all the time, because its the only way to guarantee that you'll know which object you're referring to.
The only time you need to use "self" in Lightning is when you start creating objects in code. For example, you might create some sort of helper object:
({
increment: function() {
// this refers to the helper object
// but self refers to the object created in getHelper
// this.counter++ would crash; this.counter is undefined
self.counter++; // Increments the helper's counter
},
getHelper: function() {
return (function() {
var self = this;
self.counter = 0;
return {
increment: increment
};
})();
}
})
I apologize for the complexity of this code, but hopefully it demonstrates when you'd want to use self instead of this.
I suggest you read up on the documentation for this
on MDN.
A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
In most cases, the value of this is determined by how a function is called. It can't be set by assignment during execution, and it may be different each time the function is called. ES5 introduced the bind method to set the value of a function's this regardless of how it's called, and ES6 introduced arrow functions whose this is lexically scoped (it is set to the this value of the enclosing execution context).
In other words, it's complicated. It depends on context, and even which version of Javascript is running!
Context can change what is held in the this
variable. For example, inside of your anonymous callback function, it isn't immediately clear whether this
refers to what it did on the line before, or if it refers to action
, or response
, or something else. Basically, you make your callback less context dependent.
Consider this page:
<apex:page>
<button>Click Me!</button>
<script>
(function (D, w) {
"use strict";
var N = w.myNamespace = w.myNamespace || {}
N.doStuff = function () {
var self = this;
[].forEach.call(D.getElementsByTagName("button"), function (element) {
console.debug(self);
console.debug(this);
element.addEventListener("click", function (event) {
console.debug(self);
console.debug(this);
});
});
}
D.addEventListener("DOMContentLoaded", N.doStuff);
}(document, window));
</script>
</apex:page>
The onload
debugs will yield:
#document
undefined
However, if you then call myNamespace.doStuff
from the console, you will get:
Object { }
undefined
And if you click the button, you will get:
#document
<button>Click Me!</button>
Be wary of using this
if you aren't sure what it is in a given context. Even if you alias it to self
, the context in which you do so has the same issue.