Pergunta

Essa coisa quase funciona:

function myClass(url) {

this.source = url;
this.rq = null;
this.someOtherProperty = "hello";

// open connection to the ajax server
this.start = function() {
    if (window.XMLHttpRequest) {
        this.rq = new XMLHttpRequest();
        if (this.rq.overrideMimeType)
        this.rq.overrideMimeType("text/xml"); 
    } else
        this.rq = new ActiveXObject("Microsoft.XMLHTTP");

    try {
        this.rq.onreadystatechange = connectionEvent;
        this.rq.open("GET", this.source, true);
        this.rq.send(null);
        this.state = 1;
    } catch (err) {
        // some error handler here
    }

}

function connectionEvent() {
    alert("i'm here");
    alert("this doesnt work: " + this.someOtherProperty);
}

} // minha classe

Portanto, nada mais é do que ter o objeto xmlhttprequest como membro da minha classe, em vez de definido globalmente, e invocando -o da maneira tradicional. No entanto, dentro da minha função de retorno de chamada do ConnectionEvent, o significado de "isso" é perdido, mesmo que a função seja escopo dentro da MyClass. Também me certifiquei de que o objeto que instancie da MyClass seja mantido vivo por tempo suficiente (declarado global no script).

Em todos os exemplos de uso de classes JavaScript que eu vi, "This" ainda estava disponível dentro das funções internas. Para mim, não é, mesmo que eu aceite minha função do lado de fora e faça dela um myclass.prototype.connectionEvent. O que estou fazendo errado? obrigada.

Foi útil?

Solução

A razão pela qual não está funcionando é que em JavaScript, this é definido inteiramente por como uma função é chamado, não onde está definido. Isso é diferente de alguns outros idiomas.

Ter this significa o que você espera, teria que garantir isso explicitamente "vinculando":

this.start = function() {
    var self = this; // Set up something that survives into the closure

    /* ...lots of stuff omitted... */

    this.rq.onreadystatechange = function() {
        // Call `connectionEvent`, setting `self` as `this` within the call
        connnectionEvent.call(self);
    };

Há mais informações sobre this gestão em esta postagem do blog, mas basicamente: quando uma função é chamada sem nenhum esforço particular feito para definir this, this dentro da função estará sempre o objeto global (window, em navegadores). Existem duas maneiras de definir this Ao fazer uma chamada:

  1. Usando Function#call (ou Function#apply) como eu fiz acima, passando na referência de objeto para usar como this como o primeiro parâmetro. Que chama a função e define this para tudo o que você passou. A diferença entre #call e #apply é assim que você fornece argumentos adicionais para passar para a função. Com #call você os fornece como argumentos adicionais para o #call Ligue (por exemplo func.call(thisArg, arg0, arg1, arg2)), enquanto que com #apply Você os fornece como uma matriz no segundo argumento (func.apply(thisArg, [arg0, arg1, arg2])).
  2. Usando notação pontilhada: se você tem um objeto que possui uma propriedade com uma função atribuída a ele (como o seu start propriedade), chamando isso usando a instância do objeto, um ponto e o nome da propriedade (this.start() ou foo.start(), etc.) chamará a função e definirá this para a instância do objeto dentro da chamada. Então a notação pontilhada faz dois totalmente distinto Coisas: procure a propriedade e encontra uma função como seu valor, e chama a função de tal forma que this está definido como o objeto durante a chamada. Literalmente é como: var f = obj.func; f.call(obj).

Um pouco fora do tópico, mas: exceto uma boa razão para, eu não reinventaria essa roda. Existem muitas bibliotecas por aí para simplesmente XHR chamadas. jQuery, Protótipo, Fecho, e quase todo o resto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top