2010-10-25 12 views
42

Sono nuovo di JavaScript. Nuovo per quanto ne ho fatto veramente, è stato ottimizzato il codice esistente e scritto piccoli bit di jQuery.'questo' non è definito nei metodi della classe JavaScript

Ora sto tentando di scrivere una "classe" con attributi e metodi, ma ho problemi con i metodi. Il mio codice:

function Request(destination, stay_open) { 
    this.state = "ready"; 
    this.xhr = null; 
    this.destination = destination; 
    this.stay_open = stay_open; 

    this.open = function(data) { 
     this.xhr = $.ajax({ 
      url: destination, 
      success: this.handle_response, 
      error: this.handle_failure, 
      timeout: 100000000, 
      data: data, 
      dataType: 'json', 
     }); 
    }; 

    /* snip... */ 

} 

Request.prototype.start = function() { 
    if(this.stay_open == true) { 
     this.open({msg: 'listen'}); 
    } else { 

    } 
}; 
//all console.log's omitted 

Il problema è, in Request.prototype.start, this è indefinito e quindi l'istruzione if restituisce false. Cosa sto facendo di sbagliato qui?

+0

C'è un motivo per cui hai 'start' nel' prototipo'? – xj9

+0

A cosa serve 'Request.prototype'? –

+0

Non ho idea: S –

risposta

43

Come si chiama la funzione di avvio?

Questo dovrebbe funzionare (nuova è la chiave)

var o = new Request(destination, stay_open); 
o.start(); 

Se si chiama direttamente piace Request.prototype.start(), this farà riferimento al contesto globale (window nei browser).

Inoltre, se this non è definito, si verifica un errore. L'espressione if non valuta false.

Aggiornamento: this oggetto non è impostato sulla base di dichiarazione, ma invocazione. Ciò significa che se si assegna la proprietà della funzione a una variabile come x = o.start e si chiama x(), this all'interno di start non si riferisce più a o. Questo è quello che succede quando fai setTimeout. Per farlo funzionare, invece:

var o = new Request(...); 
setTimeout(function() { o.start(); }, 1000); 
+0

Sto usando setTimeout: 'var ascolta = new Request (destination, stay_open); setTimeout (listen.start, 500); ' –

+0

Sì, non funzionerebbe. Aggiornerò la mia risposta –

+0

eccellente, grazie –

15

L'OOP di JavaScript è un po 'funky (o molto) e ci vuole un po' per abituarsi. Questa prima cosa che devi tenere a mente è che non ci sono Classi e pensare in termini di classi può farti inciampare. E per utilizzare un metodo collegato a un Costruttore (l'equivalente JavaScript di una definizione di Classe) è necessario creare un'istanza dell'oggetto. Per esempio:

Ninja = function (name) { 
    this.name = name; 
}; 
aNinja = new Ninja('foxy'); 
aNinja.name; //-> 'foxy' 

enemyNinja = new Ninja('boggis'); 
enemyNinja.name; //=> 'boggis' 

Nota che Ninja casi hanno le stesse proprietà, ma aNinja non possono accedere alle proprietà di enemyNinja. (Questa parte dovrebbe essere molto facile/semplice) Le cose si fanno un po 'diverso quando si inizia ad aggiungere roba alla prototype:

Ninja.prototype.jump = function() { 
    return this.name + ' jumped!'; 
}; 
Ninja.prototype.jump(); //-> Error. 
aNinja.jump(); //-> 'foxy jumped!' 
enemyNinja.jump(); //-> 'boggis jumped!' 

chiamata a questo direttamente genera un errore perché this punti solo per l'oggetto corretto (il vostro "Class ") quando il costruttore è istanziato (altrimenti si indica l'oggetto globale, window in un browser)

3

in ES2015 aka ES6, class è uno zucchero sintattico per functions.

Se si desidera forzare l'impostazione di un contesto per this è possibile utilizzare il metodo bind(). Come indicato da @chetan, su invocazione puoi anche impostare il contesto!Controllare il seguente esempio:

class Form extends React.Component { 
constructor() { 
    super(); 
    } 
    handleChange(e) { 
    switch (e.target.id) { 
     case 'owner': 
     this.setState({owner: e.target.value}); 
     break; 
     default: 
    } 
    } 
    render() { 
    return (
     <form onSubmit={this.handleNewCodeBlock}> 
     <p>Owner:</p> <input onChange={this.handleChange.bind(this)} /> 
     </form> 
    ); 
    } 
} 

Eccoci costretti contesto all'interno handleChange()-Form.

Problemi correlati