为什么面向对象中addEventListener找不到属性或者无法移除事件?


以下两短代码都表示一个简单功能,描述为:我想要的效果是,鼠标按下后,在页面移动不断计数,鼠标抬起则移除事件。但是下面的代码都有问题。

第一段代码的问题,找不到removeEventListener属性:


 function counter (obj){
        this.obj = obj;
        this.num = 0;
    }

    counter.prototype.start = function(){
        var self = this;
        self.obj.addEventListener( "mousemove" , self.move , false );
        self.obj.addEventListener( "mouseup" , self.end , false );
    }

    counter.prototype.move = function(){
        var self = this;
        document.title = self.num++;
    }

    counter.prototype.end = function(){
        var self = this;
        self.obj.removeEventListener( "mousemove" , self.move , false );
        self.obj.removeEventListener( "mouseup" , self.end , false );
    }

    counter.prototype.init = function(){
        var self = this;
        self.obj.addEventListener( "mousedown" , self.start , false );
    }


    var counterNew = new counter(document);

    counterNew.init();

以上代码在init中有修改,原来是 self.end,搞错了,应该是 self.start

第二段代码的问题,可能是因为绑定和删除都是匿名函数,所以无法移除事件:


 function counter (obj){
        this.obj = obj;
        this.num = 0;
    }

    counter.prototype.start = function(){
        var self = this;
        self.obj.addEventListener( "mousemove" , function(){
            self.move();
        } , false );
        self.obj.addEventListener( "mouseup" , function(){
            self.end();
        } , false );
    }

    counter.prototype.move = function(){
        var self = this;
        document.title = self.num++;
    }

    counter.prototype.end = function(){
        var self = this;
        self.obj.removeEventListener( "mousemove" , function(){
            self.move();
        } , false );
        self.obj.removeEventListener( "mouseup" , function(){
            self.end();
        } , false );
    }

    counter.prototype.init = function(){
        var self = this;
        self.obj.addEventListener( "mousedown" , function(){
            self.start();
        } , false );
    }


    var counterNew = new counter(document);

    counterNew.init();

请问大家,有解决方案吗?多谢了

oop this的用法 javascript面向对象 JavaScript

园艺师之剪 9 years, 8 months ago

关注中,我也遇到过这个bug

喵森あおい answered 9 years, 8 months ago

@不写代码的码农 @kikong 好像不对吧。以下是我用面向对象实现的,按照面向对象来说,对不同obj来说,计数都是相对独立的。可是你以上面向对象写的,好像计数叠加在一起了:


 function bind(fn, context) {
        return function () {
            return fn.apply(context, arguments);
        };
    }

    function counter (obj){
        this.obj = obj;
        this.num = 0;
    }

    counter.prototype.start = function(){   
        this.obj.onmousemove = bind(this.move,this);
        this.obj.onmouseup = bind(this.end,this);
    }

    counter.prototype.move = function(){
        this.num++;
        document.title = this.num;

    }

    counter.prototype.end = function(){
        this.obj.onmousemove = this.obj.onmouseup = null;
    }

    counter.prototype.init = function(){
        this.obj.onmousedown = bind(this.start,this);
    }

    var popupBox = document.getElementById("popup-box"),
        box = document.getElementById("box");

    var counterNew = new counter(popupBox),
        counterBox = new counter(box);

    counterNew.init();
    counterBox.init();

blooful answered 9 years, 8 months ago

js中函数有3种调用方式
1)作为对象的方法,此时this为方法所在的对象
2)作为普通函数调用,此时this为全局对象
3)通过call/apply调用,此时this为传入的对象
问题中,self.end 获取函数对象作为 mousedown 事件的处理函数;
此时就是普通函数调用方式,this指的是全局对象,也就是window

所以就报错啦~~~~

==可以修改下,看下是否符合你的预期=====
==在init方法中完成事件监听工作


 function counter (obj){
        this.obj = obj;
        this.num = 0;
    }
    /*
    counter.prototype.start = function(){
        var self = this;
        self.obj.addEventListener( "mousemove" , self.move , false );
        self.obj.addEventListener( "mouseup" , self.end , false );
    }

    counter.prototype.move = function(){
        var self = this;
        document.title = self.num++;
    }

    counter.prototype.end = function(){
        var self = this;
        self.obj.removeEventListener( "mousemove" , self.move , false );
        self.obj.removeEventListener( "mouseup" , self.end , false );
    }
    */

    counter.prototype.init = function(){
        var self = this;
        function mousemoveHandler(){
             document.title = self.num++;
        }
        function mouseupHandler(){
            self.obj.removeEventListener( "mousemove" , mousemoveHandler , false );
            self.obj.removeEventListener( "mouseup" , mouseupHandler , false );
        }

        function mousedownHandler(){
            self.obj.addEventListener( "mousemove" , mousemoveHandler , false );
            self.obj.addEventListener( "mouseup" , mouseupHandler , false );
        }
        self.obj.addEventListener( "mousedown" , mousedownHandler , false );




    }


    var counterNew = new counter(document);

    counterNew.init();

强势D废材 answered 9 years, 8 months ago

第一段代码解决方案:


 counter.prototype.init = function(){
            var self = this;
            self.obj.addEventListener( "mousedown" , function(){
                self.end();
            } , false );
        }

原因: self.obj.addEventListener( "mousedown" , self.end , false ); self.end 函数中的 this 指向了 document

yiming answered 9 years, 8 months ago

非面向对象实现


 //非面向对象实现
        var num1 = 0;

        function start(){
            num1++;
            document.title = num1;
        }
        document.addEventListener("mousedown",function(){
            this.addEventListener("mousemove",start,false);
        },false);
        document.addEventListener("mouseup",function(){
            this.removeEventListener("mousemove",start,false);
        });

面向对象实现


 function Counter(obj){
            this.num = 0;
            this.obj = obj;
        }
        Counter.prototype.countNum = function(){
            that.num++;
            this.title = that.num;
        }
        Counter.prototype.mdStart = function(){
            this.addEventListener("mousemove",that.countNum,false);
        }
        Counter.prototype.mdEnd = function(){
            this.removeEventListener("mousemove",that.countNum,false);
        }
        Counter.prototype.start = function(){
            that = this;
            this.obj.addEventListener("mousedown",that.mdStart,false);
            this.obj.addEventListener("mouseup",that.mdEnd,false);
        }
        Counter.prototype.end = function(){
            this.addEventListener("mouseup",this.mdEnd,false);
        }
        Counter.prototype.init= function(){
            this.start();
        }

         var counterNew = new Counter(document);
         counterNew.init();

第二种也可以通过 call 或者 apply 实现,TZ可以试试

保护野生动物 answered 9 years, 8 months ago

Your Answer