Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [JS OOP] - metodo che perde riferimento alla classe

    Ciao,
    in una piccola classe per il lancio di chiamate Ajax, un metodo chiama una funzione creata al volo, ma al suo interno viene perso il riferimento this alla classe.

    Come posso richiamare il metodo XMLparse() per parsare il responso?

    codice:
    <html>
    <head>
    <script type="text/javascript">
    <!--
    function ajaxCall(URL) {
    	this.URL = URL;
    	
    	this.XMLparse = function(XMLresponse) {
    		// parses the XML response and returns the HTML output string;
    		if (window.ActiveXObject) {
    			// MSIE:
    			var doc = new ActiveXObject("Microsoft.XMLDOM");
    			doc.async = "false";
    			doc.loadXML(XMLresponse);
    		} else {
    			// W3C compliant:
    			var parser = new DOMParser();
    			var doc = parser.parseFromString(XMLresponse, "text/xml");
    		}
    		var XMLdoc = doc.documentElement;
    		var value = XMLdoc.getElementsByTagName('value').item(0).firstChild.nodeValue;
    		return value;
    	};
    	this.createXmlHttp = function() {
    		var xmlHttp;
    		try {
    			// W3C compliant:
    			xmlHttp = new XMLHttpRequest();
    			return xmlHttp;
    		} catch(e) {
    			// MSIE:
    			try {
    				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    				return xmlHttp;
    			} catch(e) {
    				try {
    					xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    					return xmlHttp;
    				} catch(e) {
    					alert("Your browser does not support AJAX.");
    					return false;
    				}
    			}
    		}
    	};
    	this.getResponse = function() {
    		var el = document.getElementById('result');
    		var xmlHttp = this.createXmlHttp();
    		xmlHttp.onreadystatechange = function() { // qui perdo il riferimento
    			document.getElementById('requestStatus').innerHTML = "Request status = " + xmlHttp.readyState;
    			if (xmlHttp.readyState == 4) {
    				document.getElementById('xmlHttpStatus').innerHTML = "HTTP status = " + xmlHttp.status;
    				el.innerHTML += this.XMLparse(xmlHttp.responseText);
    			}
    		}
    		var timestamp = new Date().getTime();
    		xmlHttp.open("GET", this.URL + "?request=" + timestamp, true);
    		xmlHttp.send(null);
    	};
    }
    
    var request = new ajaxCall("file.xml");
    //-->
    </script>
    </head>
    <body>
    
    <div id="result"></div>
    <div id="requestStatus"></div>
    <div id="xmlHttpStatus"></div>
    
    <input type="button" value="send request and parse" onclick="request.getResponse();" />
    
    </body>
    </html>
    La JS console di Firefox dice:
    Errore: this.XMLparse is not a function

    Il file "file.xml" contiene un semplice campo:

    codice:
    <?xml version="1.0" encoding="UTF-8" ?>
    <response>
         <value>true</value>
    </response>

    [Il problema è sicuramente lì perché senza passare il responso al metodo XMLparse, questo viene visualizzato correttamente nel DIV apposito.]
    Emanuele DG
    <?php echo "Proverbio zen(d): vivi ogni giorno come se fosse il ".date('d M Y', time()); ?>
    Intellectual property

  2. #2
    non ho controllato, ma velocemente basta fare cosi:

    codice:
    var that=this;
    
    xmlHttp.onreadystatechange = function() { // qui perdo il riferimento
    			document.getElementById('requestStatus').innerHTML = "Request status = " + xmlHttp.readyState;
    			if (xmlHttp.readyState == 4) {
    				document.getElementById('xmlHttpStatus').innerHTML = "HTTP status = " + xmlHttp.status;
    				el.innerHTML += that.XMLparse(xmlHttp.responseText);
    			}
    		}

  3. #3

    Scope rules

    Originariamente inviato da kentaromiura
    non ho controllato, ma velocemente basta fare cosi:

    codice:
    var that=this;
    
    xmlHttp.onreadystatechange = function() { // qui perdo il riferimento
    			document.getElementById('requestStatus').innerHTML = "Request status = " + xmlHttp.readyState;
    			if (xmlHttp.readyState == 4) {
    				document.getElementById('xmlHttpStatus').innerHTML = "HTTP status = " + xmlHttp.status;
    				el.innerHTML += that.XMLparse(xmlHttp.responseText);
    			}
    		}
    Grazie Kentaro!
    Sapendo che nella OOP JS il riferimento a volte viene perso, avevo fatto la stessa cosa:
    var self = this;

    però sbagliavo perché passavo "self" come parametro della funzione a runtime, senza notare che lì dentro, le variabili del metodo che la richiama hanno visibilità.

    Puoi dirmi quali sono i casi in cui il riferimento viene perso? (Ovvero il funzionamento dello scope per i parametri delle classi) magari indicandomi delle risorse utili.

    Mi sono riletto per l'ennesima volta tutto il thread derivante dalla pillola di andr3a su JS OOP
    http://forum.html.it/forum/showthrea...readid=1014613

    ma non si definiscono in modo chiaro le scope rules, per capire tutte le probabili casistiche di visibilità.
    Sto cercando in rete ma su JS OOP si trova ancora poca documentazione generica che non sia mirata ad un prodotto specifico, tipo libraries, frameworks etc.
    Emanuele DG
    <?php echo "Proverbio zen(d): vivi ogni giorno come se fosse il ".date('d M Y', time()); ?>
    Intellectual property

  4. #4

    Re: Scope rules

    Originariamente inviato da emanueledg
    Sapendo che nella OOP JS il riferimento a volte viene perso
    questo caso NON esiste, this è smpre esattamente riferito a quello che ci si aspetta e nel tuo caso doppia confusione, visto che ti aspetti quel this dentro un metodo chiamato in modo asincrono di un altro oggetto.

    Originariamente inviato da emanueledg
    Puoi dirmi quali sono i casi in cui il riferimento viene perso? (Ovvero il funzionamento dello scope per i parametri delle classi) magari indicandomi delle risorse utili.
    http://www.3site.eu/doc/


    Originariamente inviato da emanueledg
    Mi sono riletto per l'ennesima volta tutto il thread derivante dalla pillola di andr3a su JS OOP
    http://forum.html.it/forum/showthrea...readid=1014613

    ma non si definiscono in modo chiaro le scope rules, per capire tutte le probabili casistiche di visibilità.
    il this, ed a cosa si riferisce, credevo fosse abbastanza chiaro.
    Il riferimento non viene mai perso, this è super object (aka window) se la funzione è chiamata senza scope o con null in apply/call, in tutti gli altri casi è l'oggetto di riferimento, ma essendo questo vero per ogni funzione, lo stesso ragionamento va fatto per ogni altrafunzione innestata.
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  5. #5

    Re: Re: Scope rules

    Originariamente inviato da andr3a
    questo caso NON esiste, this è smpre esattamente riferito a quello che ci si aspetta e nel tuo caso doppia confusione, visto che ti aspetti quel this dentro un metodo chiamato in modo asincrono di un altro oggetto.


    http://www.3site.eu/doc/



    il this, ed a cosa si riferisce, credevo fosse abbastanza chiaro.
    Il riferimento non viene mai perso, this è super object (aka window) se la funzione è chiamata senza scope o con null in apply/call, in tutti gli altri casi è l'oggetto di riferimento, ma essendo questo vero per ogni funzione, lo stesso ragionamento va fatto per ogni altrafunzione innestata.
    ci sarebbe solo un caso in un browser che può far confusione, quando l'evento è attaccato usando l' attach invece che direttamente all oggetto, a si inoltre quando si chiamano funzioni col setInterval/Timeout
    ciao,

  6. #6

    Re: Re: Scope rules

    Originariamente inviato da andr3a
    questo caso NON esiste, this è smpre esattamente riferito a quello che ci si aspetta e nel tuo caso doppia confusione, visto che ti aspetti quel this dentro un metodo chiamato in modo asincrono di un altro oggetto.


    http://www.3site.eu/doc/



    il this, ed a cosa si riferisce, credevo fosse abbastanza chiaro.
    Il riferimento non viene mai perso, this è super object (aka window) se la funzione è chiamata senza scope o con null in apply/call, in tutti gli altri casi è l'oggetto di riferimento, ma essendo questo vero per ogni funzione, lo stesso ragionamento va fatto per ogni altrafunzione innestata.
    Ciao Andrew
    Grazie per le risorse che scrivi e per i tuoi consigli sempre preziosi!
    Sì, ho fatto varie prove ed il this restituisce sempre l'oggetto di riferimento, che in quel caso è l'oggetto XMLHttpRequest di cui la funzione a runtime è un metodo.

    Quindi ho capito che quando scrivevi nella pillola "il riferimento va sempre passato nelle funzioni annidate" intendevi il riferimento alla classe a cui appartengono i metodi per le funzioni a loro volta annidate in essi.
    Leggerò ache Javascript Prototypal Inheritance.

    Per quanto riguarda la perdita del riferimento nel caso di attachEvent (e setTimeout/setInterval), finora non mi è capitato di usarlo in un contesto OOP (ma prima o poi mi servirà), e stavo leggendo questo articolo su Quirksmode sul principio di base e la compatibilità.


    Emanuele DG
    <?php echo "Proverbio zen(d): vivi ogni giorno come se fosse il ".date('d M Y', time()); ?>
    Intellectual property

  7. #7
    Dai un occhio anche a questo thread che segnala un bel link sulla perdita di binding in js.




    Ps.

    Più che altro è una questione di gusti ma avrei risolto
    in questo modo (visto che quel metodo lo utilizzi solamente
    all'interno di ajaxCall) e all'interno di XMLparse non ci sono
    this (ad esempio this.URL darebbe undefined)

    Codice PHP:
    function ajaxCall(URL) {
        
    this.URL URL;
        function 
    XMLparse(XMLresponse) {
            
    // parses the XML response and returns the HTML output string;
            
    if (window.ActiveXObject) {
                
    // MSIE:
                
    var doc = new ActiveXObject("Microsoft.XMLDOM");
                
    doc.async "false";
                
    doc.loadXML(XMLresponse);
            } else {
                
    // W3C compliant:
                
    var parser = new DOMParser();
                var 
    doc parser.parseFromString(XMLresponse"text/xml");
            }
            var 
    XMLdoc doc.documentElement;
            var 
    value XMLdoc.getElementsByTagName('value').item(0).firstChild.nodeValue;
            return 
    value;
        };
        
    this.createXmlHttp = function() {
            var 
    xmlHttp;
            try {
                
    // W3C compliant:
                
    xmlHttp = new XMLHttpRequest();
                return 
    xmlHttp;
            } catch(
    e) {
                
    // MSIE:
                
    try {
                    
    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
                    return 
    xmlHttp;
                } catch(
    e) {
                    try {
                        
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                        return 
    xmlHttp;
                    } catch(
    e) {
                        
    alert("Your browser does not support AJAX.");
                        return 
    false;
                    }
                }
            }
        };
        
    this.getResponse = function() {
            var 
    el document.getElementById('result');
            var 
    xmlHttp this.createXmlHttp();
            
    xmlHttp.onreadystatechange = function() { // qui perdo il riferimento
                
    document.getElementById('requestStatus').innerHTML "Request status = " xmlHttp.readyState;
                if (
    xmlHttp.readyState == 4) {
                    
    alert(xmlHttp===this);
                    
    document.getElementById('xmlHttpStatus').innerHTML "HTTP status = " xmlHttp.status;
                    
    el.innerHTML += XMLparse(xmlHttp.responseText);
                }
            }
            var 
    timestamp = new Date().getTime();
            
    xmlHttp.open("GET"this.URL "?request=" timestamptrue);
            
    xmlHttp.send(null);
        };
    }

    var 
    request = new ajaxCall("file.xml"); 
    Without faith, nothing is possible. With it, nothing is impossible
    http://ilwebdifabio.it

  8. #8

    Re: Re: Re: Scope rules

    Originariamente inviato da kentaromiura
    ci sarebbe solo un caso in un browser che può far confusione, quando l'evento è attaccato usando l' attach invece che direttamente all oggetto, a si inoltre quando si chiamano funzioni col setInterval/Timeout
    ciao,
    questi casi rientrano perfettamente in quanto ho gia' detto.

    la funzione in setInterval/Timeout e' chiamata senza scope, ergo il this e' il super object, regolarissimo, normale, expected behaviour.

    Se si capisce come funziona lo scope di funzioni, si capisce il 90% di JavaScript.

    attachEvent richiama la funzione senza iniettare lo scope, ergo non vedo eccezioni.

    Se lo si compara con addEvent che e' W3 e standard, si commette un altro errore, dato che attachEvent, come detachEvent, e' proprietario di IE o emulato in Opera, ma non specifica scope iniettato
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  9. #9
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  10. #10
    Without faith, nothing is possible. With it, nothing is impossible
    http://ilwebdifabio.it

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.