As I checked on MDN, method of a class looks like this:
class Foo {
method1 (){
// content of method1
}
}
However I found it’s not good for event handlers
<!doctype html>
<html lang="en">
<head>
<title>test</title>
</head>
<body>
<div class="settings">
<div>
<label for="cb1">checkbox</label>
<input id="cb1" type="checkbox"></input>
</div>
</div>
<script>
'use strict'
class TEST{
box = null;
info = {content: {blah: "blah"}};
init (){
this.box = window.document.querySelector(".settings");
this.box.addEventListener("change", this.handler);
this.box.addEventListener("change", this.handler2);
}
handler = e=> {
console.log("handler this: %o", this);
console.log("handler info: %o", this.info.content);
}
handler2 (e) {
console.log("handler2 this: %o", this);
console.log("handler2 info: %o", this.info.content);
}
}
let t = new TEST();
t.init();
</script>
</body>
</html>
In the test page above, click the checkbox then the result is
Reading about arrow function’s scope then I understand why ther’s the difference. But using arrow function to declare a method of class looks weird, did I do it correctly?
What’s more since I don’t like there’re two kind of function style in one class, I prefer using arrow function for all other methods if possible, but I’m not sure this works for constructor
or did it has any potential glitch or secure problem
Any opinion on this please?
2
Answers
handler()
is an arrow function, so it inheritsthis
from the outer scope. No worries.But with methods which are
function
s in an instance’s prototype the situation is different.When you pass a method as an argument you basically pass it alone without its context (in our case
this
). There’re several fixes how to achieve that:Use
.bind()
:Use an arrow function:
THere could be some automatic context binding like the below. Also there’re some problems with inheritance as well as in Bergi’s example (we are overriding prototypes). So that’s why binding on demand like my first 2 proposals could be preferable.
So if you want to dive deep into JS proxies and prototypes:
Yes, this works, but notice they are arrow functions in class fields and not methods.
Yes, you cannot use this style for the
constructor
, and you should not generally use this because it doesn’t work properly with inheritance (cannot be overridden properly, cannot be used withsuper
) and uses more memory than a shared prototype method – the arrow functions are created per instance.So use this only where you really need it. Alternative approaches are
creating the arrow functions explicitly in the constructor, without class field syntax:
defining methods and
.bind()
ing them explicitly in the constructor: