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

call a javascript function from within another function

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

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 函数?

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

引用 this 中的函数

你必须好好研究 SCOPE 才能理解

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

问题是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

按照更好的原型继承模型编写代码可能会更好,如下所示:

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);
        }
    });
};

这通过创建一个真实的 class 解决了上下文问题,例如:

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'