All the answers here are good, but for clarity regarding:
- I have no idea whats going on here:
this.handleRefreshClick.bind(this)
I think an example is best in describing the difference in behaviour.
// Class where functions are explicitly bound to "this" specific object
var Bindings = class {
constructor() {
this.Firstname = "Joe"
this.Surname = "Blow"
this.PrettyPrint = this.PrettyPrint.bind(this)
this.Print = this.Print.bind(this)
}
Print(inputStr) {
console.log(inputStr)
console.log(this)
}
PrettyPrint() {
this.Print(`${this.Firstname} ${this.Surname}`)
}
}
// Class where "this" context for each function is implicitly bound to
// the object the function is attached to / window / global
// identical class, except for removing the calls to .bind(this)
var NoBindings = class {
constructor() {
this.Firstname = "Joe"
this.Surname = "Blow"
}
Print(inputStr) {
console.log(inputStr)
console.log(this)
}
PrettyPrint() {
this.Print(`${this.Firstname} ${this.Surname}`)
}
}
var bindings = new Bindings()
var noBindings = new NoBindings()
bindings.PrettyPrint()
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow", PrettyPrint: PrettyPrint(), Print: Print() }
noBindings.PrettyPrint()
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow" }
// noBindings has both functions & everything works as we expect,
// if this is all you're doing, then there's practically little difference,
// but if we separate them from the original "this" context...
var b = { PPrint: bindings.PrettyPrint }
var nb = { PPrint: noBindings.PrettyPrint }
b.PPrint()
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow", PrettyPrint: PrettyPrint(), Print: Print() }
// PPrint calls "PrettyPrint" where "this" references the original "bindings" variable
// "bindings" has a function called "Print" which "PrettyPrint" calls
nb.PrettyPrint()
// > Uncaught TypeError: this.Print is not a function
// PPrint calls "PrettyPrint" where "this" references the new "nb" variable
// due to different "this" context, "nb" does not have a function called "Print", so it fails
// We can verify this by modifying "bindings" and seeing that it's reflected in "b"
bindings.Surname = "Schmo"
b.PPrint()
// > "Joe Schmo"
// > Object { Firstname: "Joe", Surname: "Schmo", PrettyPrint: PrettyPrint(), Print: Print() }
// We can also add a "Print" method to "nb", and see that it's called by PrettyPrint
nb.Print = function(inputStr) { console.log(inputStr); console.log(this) }
nb.PPrint()
// > undefined undefined
// > Object { PPrint: PrettyPrint(), Print: Print(inputStr) }
// The reason we get "undefined undefined",
// is because "nb" doesn't have a Firstname or Surname field.
// because, again, it's a different "this" context