Why couldn't I add the mousemove event after the mousedown in the prototype?
I would move my legacy js codes to a more OOP style. Here is the code.
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
function test() {
}
test.prototype = {
init: function () {
addEvent(document, 'mousedown', this.displaydown);
},
displaydown : function(e){
document.getElementById('mydiv').innerHTML = "down";
addEvent(document, 'mousemove', this.displaymove);
},
displaymove : function(e){
document.getElementById('mydiv').innerHTML = "move";
}
}
var test0 = new test();
test0.init()
I couldnt add mousemove event after mousedown with
addEvent(document, 'mousemove', this.displaymove);
But if I write inline style like
addEvent(document, 'mousemove', function(e){
document.getElementById('mydiv').innerHTML = "move";
});
Everything is good. It looks like 2 codes are doing the same thing. Why is there a difference? Thank!
change
After fighting for 2 nights, I finally solved the problem. Thanks johnvey for your understanding.
Ero occurs on the this keyword . In the case of an object, this refers to the window and not to the object itself. The solution is to define the global parameter me (me = this) at the beginning. Now everything is all right.
source to share
This is a classic Javascript sticking point, dealing with how the "this" key resides within a closure. To illustrate:
redPrinter = function() {
this.X = 'red';
return function() {
return this.X;
}
}
main = function() {
this.X = 'blue';
var myRedPrinter = new redPrinter();
alert("Red printer returned: " + myRedPrinter());
}
main();
This code will be printed:
Red printer returned: blue
since the scope 'this' is in the line:
return this.X
is actually attached to the main () object at the time of the call.
Generally, there are two ways to solve this problem:
1) Avoid using the 'this' keyword within a function closure. To fix your code this way, I simply collected all the event bindings in one place, rather than cascading them, thereby removing the 'this' references from both displaydown () and displaymove ():
test.prototype = {
init: function () {
addEvent(document, 'mousedown', this.displaydown);
addEvent(document, 'mousemove', this.displaymove);
},
displaydown : function(e){
document.getElementById('mydiv').innerHTML = "down";
},
displaymove : function(e){
document.getElementById('mydiv').innerHTML = "move";
}
}
OR
2) Use currying function to bind the scope during definition. I removed the bind () method from the Prototype library to illustrate:
// declare the global bind() method for all functions
Function.prototype.bind = function(obj) {
var method = this,
temp = function() {
return method.apply(obj, arguments);
};
return temp;
}
test.prototype = {
init: function () {
addEvent(document, 'mousedown', this.displaydown);
},
displaydown : function(e){
document.getElementById('mydiv').innerHTML = "down";
// note that we bind the method object here
addEvent(document, 'mousemove', this.displaymove.bind(this));
},
displaymove : function(e){
document.getElementById('mydiv').innerHTML = "move";
}
}
An important change here:
this.displaymove.bind(this)
which basically says, "When you call displaymove (), override the 'this' keyword in the context of the original context scope instead of the current Event object.
source to share