balteo
balteo

Reputation: 24697

Using another variable in order to initialize the knockout observables

I am just wondering why one has to use a temporary variable "that" (initialized with the currently allocated object i.e. "this") in the script below:

$(document).ready(function() {

    function ChatViewModel() {

        var that = this;

        that.userName = ko.observable('');
        that.chatContent = ko.observable('');
        that.message = ko.observable('');
        that.messageIndex = ko.observable(0);
        that.activePollingXhr = ko.observable(null);


        var keepPolling = false;

        that.joinChat = function() {
            if (that.userName().trim() != '') {
                keepPolling = true;
                pollForMessages();
            }
        }

        function pollForMessages() {
            if (!keepPolling) {
                return;
            }
            var form = $("#joinChatForm");


            that.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
                success: function(messages) {
                    console.log(messages);
                    for (var i = 0; i < messages.length; i++) {
                        that.chatContent(that.chatContent() + messages[i] + "\n");
                        that.messageIndex(that.messageIndex() + 1);
                    }
                },
                error: function(xhr) {
                    if (xhr.statusText != "abort" && xhr.status != 503) {
                        resetUI();
                        console.error("Unable to retrieve chat messages. Chat ended.");
                    }
                },
                complete: pollForMessages
            }));
            $('#message').focus();
        }

        that.postMessage = function() {
            if (that.message().trim() != '') {
                var form = $("#postMessageForm");
                $.ajax({url: form.attr("action"), type: "POST",
                    data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
                    error: function(xhr) {
                        console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
                    }
                });
                that.message('');
            }
        }

        that.leaveChat = function() {
            that.activePollingXhr(null);
            resetUI();
            this.userName('');
        }

        function resetUI() {
            keepPolling = false;
            that.activePollingXhr(null);
            that.message('');
            that.messageIndex(0);
            that.chatContent('');
        }

    }

    //Activate knockout.js
    ko.applyBindings(new ChatViewModel());

});

Why can't I just use "this"? Can anyone please explain?

Upvotes: 2

Views: 676

Answers (2)

codeVerine
codeVerine

Reputation: 762

This refers to the owner. You can rewrite your code like this :

$(document).ready(function() {

function ChatViewModel() {

    var that = this;

    this.userName = ko.observable('');
    this.chatContent = ko.observable('');
    this.message = ko.observable('');
    this.messageIndex = ko.observable(0);
    this.activePollingXhr = ko.observable(null);


    var keepPolling = false;

    this.joinChat = function() {
        if (that.userName().trim() != '') {
            keepPolling = true;
            pollForMessages();
        }
    }

    function pollForMessages() {
        if (!keepPolling) {
            return;
        }
        var form = $("#joinChatForm");


        this.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
            success: function(messages) {
                console.log(messages);
                for (var i = 0; i < messages.length; i++) {
                    that.chatContent(that.chatContent() + messages[i] + "\n");
                    that.messageIndex(that.messageIndex() + 1);
                }
            },
            error: function(xhr) {
                if (xhr.statusText != "abort" && xhr.status != 503) {
                    resetUI();
                    console.error("Unable to retrieve chat messages. Chat ended.");
                }
            },
            complete: pollForMessages
        }));
        $('#message').focus();
    }

    this.postMessage = function() {
        if (that.message().trim() != '') {
            var form = $("#postMessageForm");
            $.ajax({url: form.attr("action"), type: "POST",
                data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
                error: function(xhr) {
                    console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
                }
            });
            that.message('');
        }
    }

    this.leaveChat = function() {
        that.activePollingXhr(null);
        resetUI();
        that.userName('');
    }

    function resetUI() {
        keepPolling = false;
        that.activePollingXhr(null);
        that.message('');
        that.messageIndex(0);
        that.chatContent('');
    }

}

//Activate knockout.js
ko.applyBindings(new ChatViewModel());
//fixing bracet
});

Check this link: http://www.quirksmode.org/js/this.html

Upvotes: 1

Paul Manzotti
Paul Manzotti

Reputation: 5147

this always refers to the object that is in scope when the call has been made, and this can change depending on your code. If you want it to still be your object in a sub-function, then assigning it to a variable that won't change in value gets around this issue.

Upvotes: 5

Related Questions