Вопрос по prototype, javascript, callback, websocket – Javascript: прототипы с обратными вызовами и «это»

11

Я создаю класс на основе прототипаPerson это открывает соединение WebSocket и определяет функции обратного вызова как методы-прототипы.

Потому что внутри обратного вызоваthis будет ссылаться на объект WebSocket, я использовал другую переменную для удержанияPerson& APOS; sthis, Однако, когда я имею дело с несколькими экземплярами, переменная перезаписывается.

Вот небольшой отрывок, который показывает проблему:

function Person(name){
    self = this
    self.name = name
}

Person.prototype = {
    getName : function(){
        return self.name
    },

    openConnection : function(host, port){
        self.pointCount = 0
        self.ws = new WebSocket("ws://" + host + ":" + port)
        self.ws.onopen = self.onOpenConnection
    },

    onOpenConnection : function()   {
        console.log(this) // prints the websocket
        console.log(self) // prints the person
        self.ws.send(self.name) // works only if one person exists
    }
}

var p1 = new Person("Jonh")
var p2 = new Person("Adam")

console.log(p1.getName()) // Prints Adam
console.log(p2.getName()) // Prints Adam

p1.openConnection("localhost", 7000) // opens connection for p1
p2.openConnection("localhost", 7000) // opens another connection for p1    

Если более одногоPerson создается, то при попытке отправить сообщение через сокет я получаю следующую ошибку:

Uncaught Error: INVALID_STATE_ERR: DOM Exception 11

Похоже, чтоself определяется глобально, и моя попытка получить ручку кPerson& APOS; sthis внутри обратного вызова не получается. Любые предложения о том, как этого добиться?

@qwertymkvar делает его локальным для конструктора, что является еще одной проблемой unexplored
Вы должны объявить этоvar во-первых, среди других вопросов qwertymk

Ваш Ответ

3   ответа
1

self = this

Вы создали глобальную переменную, поэтому ваш код поврежден.

Также пытаюсь ссылатьсяself внутри прототипа не работает, используйтеthis

function Person(name){
    this.name = name
}

Person.prototype = {
    openConnection : function(host, port){
        this.pointCount = 0
        this.ws = new WebSocket("ws://" + host + ":" + port)
        this.ws.onopen = this.onOpenConnection.bind(this)
    },
    constructor: Person,    
    onOpenConnection : function()   {
        console.log(this) // prints the person
        this.ws.send(this.name) // works only if one person exists
    }
}
Error: User Rate Limit Exceeded unexplored
12

Когда вы делаете:

self = this

Вы неявно создаете глобальную переменную, которая (поскольку она глобальная) будет иметь одинаковое значение для всех экземпляров. Локальные переменные, должны иметьvar, let или жеconst перед ними, как один из них:

var self = this;
const self = this;
let self = this;

Но это не ваше решение здесь. Вы должны использоватьthis вместо. И, если вы собираетесь предоставить обратный вызов для веб-сокета, и вы хотите, чтобы человек, связанный с этим, рекомендовал вам просто поместить ссылку на объект Person в веб-сокет, чтобы затем можно было извлечь его оттуда. И что со всеми пропущенными точками с запятой в конце каждого оператора? Во всяком случае, вот некоторый исправленный код:

function Person(name){
    this.name = name;
}

Person.prototype = {
    getName : function(){
        return this.name;
    },

    openConnection : function(host, port){
        this.pointCount = 0;
        this.ws = new WebSocket("ws://" + host + ":" + port);
        // save person reference on the web socket
        // so we have access to the person from web socket callbacks
        this.ws.person = this;   
        this.ws.onopen = this.onOpenConnection;
    },

    onOpenConnection : function()   {
        // "this" will be the websocket
        // "this.person" is the person object
        console.log(this); // prints the websocket
        console.log(this.person); // prints the person
        this.send(this.person.name); // works only if one person exists
    }
}
Error: User Rate Limit Exceeded;Error: User Rate Limit Exceeded unexplored
Error: User Rate Limit Exceeded
what's with all the missing semicolons to end each statementError: User Rate Limit Exceeded
5

var напротив, он будет рассматриваться как глобальная переменная, что вызывает некоторые проблемы в вашем случае.

Пока конструктор ведет себя как положено, вы можете вместо этого сделать следующее, поэтомуname сохраняется в экземпляр Person, который вы создаете:

// Constructor
function Person(name){
    // You don't need to reference "self" here. It's already implied.
    this.name = name;
}

Кроме того, в WebSocket.onopen «этот» изменяется от экземпляра Person к экземпляру WebSocket. Вам нужно будет сохранить «Персона». для того, чтобы ссылаться на него внутри WebSocket.onopen.

// Prototype
Person.prototype = {
    getName : function(){
        // 'this' in this case refers to an instance of Person. 
        // So, when creating John, this.name will be John. 
        return this.name;
    },

    openConnection : function(host, port) {
        // Similar to getName(...), this refers to an instance of Person.
        // In your example, this.pointCount is NOT shared between John and Adam
        this.pointCount = 0;
        this.ws = new WebSocket("ws://" + host + (port ? ':' + port : ''));

        // In WebSocket.onopen below, you're working with a new scope, so you 
        // won't have access to 'this' as the Person anymore. You need to save 
        // 'this' somewhere, so you can reference it in the new scope.
        // *****
        var self = this;   

        this.ws.onopen = function() {
            // In this function, a new scope has been created. 'this' no 
            // longer refers to John/Adam (The instance of Person), but to 
            // WebSocket instead.

            console.log(this); // 'this' references the WebSocket instance
            console.log(self); // 'self' references the 'self' in the outer 
                               // scope. See *****

            // Since this = WebSocket in this scope, all we need to do
            // is this.send(...). If you'd like to obtain the refer
            // to the instance of the Person you worked with, you can
            // use the 'self' variable
            this.send(self.name); 
        };
    }
};

Надеюсь это поможет! Вот пример JSFiddle:http://jsfiddle.net/WFdbe/

Похожие вопросы