从另一个函数中调用javascript函数

时间:2015-06-15 18:11:23

标签: javascript jquery ajax javascript-objects

我正在编写一个聊天程序,但我被困在这一部分。

var Controller=function conversation() {
this.createMessageNode=function(msg,sender,time,mid){
    var newMessage;
    if(sender==sessionStorage.getItem('userid')){
        newMessage="<div class='message-sent' id='"+mid+"'>"+msg+"<span class='time'>"+time+"</span></div>";
    }else{
        newMessage="<div class='message-recv' id='"+mid+"'>"+msg+"<span class='time'>"+time+"</span></div>";
    }
    sessionStorage.setItem('lastMessage',mid);
    $('.chat-messages').append(newMessage);
}

this.getMessages=function(){
    if(sessionStorage.getItem('lastMessage')==null){
        sessionStorage.setItem('lastMessage',0);
    }
    $.ajax({url:"getmessages.php",type:"POST",data:{last:sessionStorage.getItem('lastMessage'),cid:sessionStorage.getItem('conversationid')},success:function(result) {
        var messages=JSON.parse(result);
        for (var i = 0; i < messages.length; i++) {
            createMessageNode(messages[i].message,messages[i].sender,messages[i].time,messages[i].mid);
            var cont=document.getElementById('chat-messages');
            cont.scrollTop=cont.scrollHeight;
        };
    }});
}

}

现在,当我这样做时,它显示错误

Uncaught ReferenceError: createMessageNode is not defined

现在在for循环中“this”变量指的是ajax对象。我怎样才能调用createMessageNode函数?

3 个答案:

答案 0 :(得分:1)

您的函数绑定到this对象。如果它是全局对象(最顶层的父作用域),那么您可以通过this

引用this.yourfunction中的函数

您必须正确学习SCOPE才能理解

http://www.w3schools.com/js/js_scope.asp

答案 1 :(得分:0)

问题是createMessageNode()Controller对象实例的一种方法,因此您需要在调用它时引用该实例。在没有引用实例的情况下,JavaScript引擎正在寻找当前范围内的函数,然后是每个更高的范围,直到全局范围。

通常您会使用this关键字来引用该实例,但在您的情况下,jQuery ajax调用已更改this上下文,因此您无法直接使用this

可能的解决方案是,在ajax调用之前,存储this上下文:

var that = this;

现在,在ajax成功函数中:

that.createMessageNode(messages[i].message,messages[i].sender,messages[i].time,messages[i].mid);
^^ refer to the instance

答案 2 :(得分:0)

在更好的原型继承模型之后编写代码可能会更好,例如:

function Controller() {
    this.chatMessages = $('.chat-messages');
}

Controller.prototype.createMessageNode = function (msg, sender, time, mid) {
    var newMessage;
    if (sender == sessionStorage.getItem('userid')) {
        newMessage = "<div class='message-sent' id='" + mid + "'>" + msg + "<span class='time'>" + time + "</span></div>";
    } else {
        newMessage = "<div class='message-recv' id='" + mid + "'>" + msg + "<span class='time'>" + time + "</span></div>";
    }
    sessionStorage.setItem('lastMessage', mid);
    this.chatMessages.append(newMessage);
};

Controller.prototype.getMessages = function () {
    var _this = this;

    if (sessionStorage.getItem('lastMessage') === null) {
        sessionStorage.setItem('lastMessage', 0);
    }

    $.ajax({
        url: "getmessages.php",
        type: "POST",
        data: {
            last: sessionStorage.getItem('lastMessage'),
            cid: sessionStorage.getItem('conversationid')
        },
        success: function (result) {
            var messages = JSON.parse(result);
            for (var i = 0; i < messages.length; i++) {
                _this.createMessageNode(messages[i].message, messages[i].sender, messages[i].time, messages[i].mid);
            }
            var cont = $('#chat-messages');
            cont.scrollTop(cont.scrollHeight);
        }
    });
};

这通过创建一个真正的类来解决上下文的问题,例如:

var conversation = new Controller();
conversation.getMessages();
conversation.createMessageNode('Hello, World!', 'JimmyBoh', new Date(), 8268124);

此外,每当你有嵌套函数时,它可以帮助将所需的上下文存储在局部变量中,例如_thisthat等。这是一个更简单的例子:

function outer() {
    // Temporarily store your desired context.
    var _this = this;

    // Make any call that executes with a different context.
    $.ajax({
        url: "getmessages.php",
        type: "GET",
        success: function inner(result) {
            _this.doSomething(result);
        }
    });
};

最后,您可能希望在与当前不同的上下文中执行方法。 .call().apply()可用于运行具有指定上下文和参数的方法。例如:

function printThis() {
    console.log(this.toString());
    console.dir(arguments);
}

printThis.call('Hello, World!');
printThis.call('Call array:', [2, 4, 6, 8], 10);   // Keeps arguments as-is.
printThis.apply('Apply array:', [2, 4, 6, 8], 10); // Accepts an array of the arguments.


function Sum(startingValue) {
    this.value = startingValue || 0;
}

Sum.prototype.add = function (number) {
    this.value += number;
}

var realSum = new Sum(2);
var fakeSum = {
    value: 3
};

realSum.add(1);
Sum.prototype.add.call(fakeSum, 2);

console.log(fakeSum.value); // Prints '5'
console.log(realSum.value); // Prints '3'