The problem is that this
is not what you think it is here:
document.getElementById("b").addEventListener("click", function(){
nw = new A();
console.log(this.mp);
});
You are associating an event handler click
with the b button. And within that controller, you create a new A()
and assign it to nw
. Then you do this.mp
... But this
in that context is the b button, which does not contain any method mp
; that's why you receive undefined
. It is nw
that contains the method, so you should do nw.mp()
. But there is still more. mp
takes a parameter with the string and you would not be passing anything. You have to pass the string with the value of the text field a.
Changing those two things, it would work:
document.getElementById("b").addEventListener("click", function() {
nw = new A();
console.log(nw.mp(document.getElementById("a").value));
});
As you can see in this demo:
function A() {
this.mp = function(msg) {
this.c = msg.length >= 15 ? true : false;
return this.c;
};
var to = (function() {
window.addEventListener("load", function() {
document.getElementById("b").addEventListener("click", function() {
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
});
});
}).bind(this)();
}
document.getElementById("b").addEventListener("click", function() {
nw = new A();
console.log(nw.mp(document.getElementById("a").value));
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<input type="text" id="a" placeholder="Mensaje" />
<input type="button" id="b" value="Enviar mensaje" />
</body>
</html>
In the comments, you say why it does not work even when it is similarly put in the internal function to
. I will explain in this edition why that is the case and why it is the expected behavior (and also why it should not be done that way).
We are going to analyze the code:
var to = (function() {
window.addEventListener("load", function(){
document.getElementById("b").addEventListener("click", function(){
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
});
});
}).bind(this)();
You create a function (that you automatically call trying to change the this
with bind
) that adds a controller of the event load
of the window in which a controller of the event click
will be put to the button ... and here is the first problem.
The window has already been loaded before calling to
(because it is called when the button has already been clicked, see problem with this later). Then adding an event handler load
to window
does not produce any results because that event has already been fired and will not fire again. We are going to eliminate it:
var to = (function() {
document.getElementById("b").addEventListener("click", function(){
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
});
}).bind(this)();
Perfect. Now with this code the controller of click
is triggered ... although you have to press a second time to trigger the controller that was just associated but we received an error:
Uncaught TypeError: this.mp is not a function at HTMLInputElement.
Why does that happen? For the same reason I commented at the beginning of this answer: this
is not what you think it is. Even if you changed the value of this
with bind
, you are now inside the function of the event handler click
and the this
has changed to be the button. This could be solved by changing the value of this
in the controller by calling bind
again:
var to = (function() {
document.getElementById("b").addEventListener("click", (function(){
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
}).bind(this));
}).bind(this)();
Perfect! It works ... or not? Now it finally returns the correct value, but there is an additional problem - every time I press the button the result is shown once more: the first time it is displayed once, the second time it is displayed twice, the third time it is displayed Show three times ... and like that.
Why does that happen? Now you have to look at another culprit:
document.getElementById("b").addEventListener("click", function(){
nw = new A();
//console.log(this.mp);
});
Each time the button is pressed, the controller function is called, a A()
is created, which calls its to
, which associates a new controller with the button ... so every time it is press the button, a new controller is being associated. That's why now the result is shown multiple times.
How could I solve that? Well, there are different modes. But perhaps it would be best if an event handler click
were not associated with the button inside to
. This way you would kill two birds with one stone: the actions will not be repeated multiple times and you will not have to press the button twice to see the result.
Then the code of to
would look like this:
var to = (function() {
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
}).bind(this)();
And the final code would look like this:
function A() {
this.mp = function(msg) {
this.c = msg.length >= 15 ? true : false;
return this.c;
};
var to = (function() {
this.mp(document.getElementById("a").value.toString());
console.log(this.c);
}).bind(this)();
}
document.getElementById("b").addEventListener("click", function() {
nw = new A();
});
<input type="text" id="a" placeholder="Mensaje" />
<input type="button" id="b" value="Enviar mensaje" />