Consider this basic TypeScript script
class foo {
v: number = 1;
public bar() {
console.log(this.v);
}
}
var a = new foo();
var b = new foo();
document.getElementById('test').addEventListener("click", a.bar);
document.getElementById('test').addEventListener("click", b.bar);
and the HTML
<html lang="en">
<body>
<button id="test">Test</button>
</body>
</html>
The expected output should be two lines with the number "1".
However, instead of that, I only receive an undefined
output.
Upon inspecting the generated JavaScript file
var foo = (function () {
function foo() {
this.v = 1;
}
foo.prototype.bar = function () {
console.log(this.v);
};
return foo;
}());
var a = new foo();
var b = new foo();
document.getElementById('test').addEventListener("click", a.bar);
document.getElementById('test').addEventListener("click", b.bar);
//# sourceMappingURL=Test.js.map
Due to performance reasons, TypeScript places the function on the prototype! Thus, the addEventListener
call was essentially adding the prototype (static) function twice as it is the same instance. This explains why I am only receiving one output instead of two.
The main issue arises from the fact that the this
keyword within the prototype function refers to the button element which does not contain a property named v
!
If we implement this in native JavaScript
var foo = function () {
this.v = 1;
var that = this;
this.bar = function () {
console.log(that.v);
}
}
var a = new foo();
var b = new foo();
document.getElementById('test').addEventListener("click", a.bar);
document.getElementById('test').addEventListener("click", b.bar);
We would achieve the desired result!
Is this a known limitation for TypeScript where class methods cannot be used as event handlers?
Furthermore, how can I remove that handler after it has been added?