Funzione onClick “this” Restituisce l’object Window

Mi sono imbattuto in un problema di graffiare la testa con la mia applicazione JavaScript.

Se scrivo un elemento come questo:

  • Ottengo “LI”.

    Tuttavia se faccio questo:

     
  • Dove “pippo ()” è:

     function foo(){ alert(this.tagName); } 

    Ottengo “indefinito”.

    Sono assente come “questo” dovrebbe funzionare in relazione alle funzioni allegate. Ma, sono sconcertato perché “questo” non sta raccogliendo l’elemento, ma apparentemente in modo predefinito a “finestra“. Non riesco a capire perché questo sta accadendo.

    Qualcuno ha una spiegazione?

    Questo perché non stai passando un riferimento a questo nella chiamata della funzione JavaScript. questo nella funzione JavaScript non si riferisce allo stesso object come nell’esempio onClick . Prova questo invece:

      
  • function foo(item){ alert(item.tagName); }

    In un ascoltatore in linea:

     > 
  • Il valore dell’attributo onclick è effettivamente racchiuso in una funzione e chiamato con l’elemento impostato su questo, ad es

     function anon() { /* attribute value */ } anon.call(element); 

    Quando metti una funzione nel corpo, stai essenzialmente ottenendo:

     function anon() { foo(); } 

    Qui, this all’interno di anon sarà l’elemento, ma dato che foo viene chiamato senza settarlo, sarà indefinito. In modalità non rigida, this sarà predefinita per l’object globale ( window in un browser). In modalità rigorosa, this dentro foo sarà indefinito.

    Una soluzione è passare un riferimento di elemento alla funzione:

     
  • quindi nella funzione:

     function foo(callingElement) { ... } 

    o anche:

     
  • function foo() { var callingElement = this; }
  • Come già detto in altre risposte, il valore di this dipenderà dal modo in cui viene chiamata la funzione che lo contiene. Ma dal momento che il tuo esempio riguarda i gestori di eventi, vorrei evidenziare ciò che cjc343 ha detto sui commenti:

    Potresti trovarlo più sensato se rimuovi i gestori eventi in linea.

    È piuttosto semplice, in realtà. Considerando questo HTML:

     
    • item 1
    • item 2
    • item 3

    Il seguente codice JavaScript terrà conto sia della rimozione dei gestori in linea, sia dell’utilizzo della delega:

     var list = document.getElementById('list'); list.addEventListener('click', function(evt){ console.log("this is the element the event is bound to: " + this.id); console.log("the event target is the clicked element: " + evt.target.id); }); 

    http://jsfiddle.net/J3Gje/

    Funzionerà su tutti i browser compatibili con il modello di eventi W3C, incluso IE9. Per IE meno recenti, è necessario utilizzare attachEvent anziché addEventListener e anteporre i nomi degli eventi con "on" . Maggiori dettagli qui .

    Un’altra opzione, quindi non devi passare questo come un parametro, è utilizzare la chiamata o applicare . È un meccanismo integrato per impostare il valore di questo all’interno di una funzione. Anche se vorrei sottolineare, aggiungere i gestori di eventi direttamente al tuo html è un po ‘antiquato. Potresti voler controllare un framework JS per la delega degli eventi ( jQuery , Prototype , Dojo , YUI , ecc.).

    fiddle: http://jsfiddle.net/bboone/Q2CkV/2/

    HTML

     
    test
    test2

    JS

     function foo(){ alert(this.tagName); } 

    Se non hai familiarità con JavaScript, non utilizzare la parola chiave this o new , in quanto potresti sbagliare o il tuo codice sarà inutilmente inefficiente e più complesso. Quello che stai cercando di realizzare, però è il seguente:

     
  • some text
  • In questo esempio, l’evento click di quell’elemento dell’elenco triggers una funzione denominata foo. La parola chiave è passata come variabile. this parola chiave si riferisce semplicemente all’ quadro che ha chiamato la funzione in questione e, se non riesce a trovare quell’ quadro, farà riferimento all’object della window del browser. In questo caso l’ quadro che ha chiamato la funzione è il nodo dell’elemento della lista dal DOM.

    Continuo a suggerire di non usare mai this parola chiave per evitare questo tipo di confusione andando avanti.

    EDIT: Inoltre, non utilizzare una proprietà tagName in quanto non è standard. Utilizzare invece la proprietà nodeName .