js:keypress事件中对象的范围

时间:2014-08-23 15:23:51

标签: javascript

这是我的JS简单脚本:

var Chat = function() {
    console.log("init");
    this.debug = function (txt) {
        console.log(txt);
    }
    document.getElementById('shoutBoxInput').addEventListener("keypress", keyPressedFunction, false);
    this.keyPressedFunction = function(e){
        console.log("keyPressed");
    }   

    this.sendText = function() {
        var texte = document.getElementById('shoutBoxInput').value;
        if (texte=="") return;
        document.getElementById('shoutBoxInput').value =""
        this.debug("sendTexte:"+texte);     
    }
    this.receiveText = function(username, texte) {      
    }

}
var chat = new Chat();

我的问题来自:

    document.getElementById('shoutBoxInput').addEventListener("keypress", keyPressedFunction, false);
    this.keyPressedFunction = function(e){

错误未捕获的ReferenceError:未定义keyPressedFunction

如果我使用:

document.getElementById('shoutBoxInput').addEventListener("keydown", this.keyPressedFunction, true);

然后永远不会调用keyPressedFunction。

小提琴:http://jsfiddle.net/ghLfhb6z/

3 个答案:

答案 0 :(得分:2)

在使用它的参考之前放置你的函数...然后使用this.keyPressedFunction ...然后'keypress'是一个有效的本机js事件? http://jsfiddle.net/ghLfhb6z/4/

是的,我告诉过的错误,实际上最重要的是将事件处理程序放在最后,检查正确的事件,如果函数在此处使用它:

var Chat = function() {
    console.log("init");
    this.debug = function (txt) {
        console.log(txt);
    }

    this.keyPressedFunction = function(e){
        console.log("keyPressed");
    }   

    this.sendText = function() {
        var texte = document.getElementById('shoutBoxInput').value;
        if (texte=="") return;
        document.getElementById('shoutBoxInput').value =""
        this.debug("sendTexte:"+texte);     
    }
    this.receiveText = function(username, texte) {      
    }
    // place this at the end
    document.getElementById('shoutBoxInput').addEventListener("keydown", this.keyPressedFunction, false);
}
var chat = new Chat();

答案 1 :(得分:2)

让我们从问题开始,然后转向你的代码的危险。

问题在于,当您致电addEventListener时,this.keyPressedEvent尚不存在:

// this.keyPressedFunction doesn't exist...so you are registering a 'keypress'
// event to undefined.
document.getElementById('shoutBoxInput').addEventListener("keypress",
    keyPressedFunction, false);
// now you define this.keyPressedFunction
this.keyPressedFunction = function(e){
    console.log("keyPressed");
}
// so this is where you should be attaching it to the event

你可能正在考虑JavaScript的托管机制,并且想“啊,this.keyPressedFunction定义被提升到这个函数的顶部,所以它可用于分配。”但是吊装仅适用于变量和函数定义;您正在做的是为成员属性分配匿名函数,因此吊装不适用。

现在危险了:

当您使用方法(对象的函数属性)进行回调时,调用该回调时this的含义将丢失。 (我知道你目前没有在回调中使用this,但最终你可能会!)换句话说,当按下某个键并调用keyPressedFunction时,{{1}的值不会是你期望的。这样做的结果是你必须非常小心地为回调或事件分配方法。如果你想这样做,你将不得不使用Function.prototype.bind。这是您的代码以正确的顺序重写,并使用this

bind

答案 2 :(得分:0)

@dmidz提供了一个可以解决您问题的正确答案,但是如果您的keyPressedFunction只需要引用Chat()模块中的代码,那么您就不需要将它们设为属性thisChat):

var Chat = function() {
    console.log("init");

    function debug(txt) {
        console.log(txt);
    }

    function keyPressedFunction(e){
        console.log("keyPressed");
    }   

    this.sendText = function() {
        var texte = document.getElementById('shoutBoxInput').value;

        if (texte=="") return;

        document.getElementById('shoutBoxInput').value ="";

        debug("sendTexte:"+texte);     
    }

    this.receiveText = function(username, texte) {      
    }

    document.getElementById('shoutBoxInput')
            .addEventListener("keypress", keyPressedFunction, false);
}

如果你这样做,那么你在使用它们之前不一定要声明你的功能,但这样做仍然是一种很好的风格。