Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669

    Oggetti e prototipi: problema insolubile?

    Salve a tutti
    Per mio uso e consumo sto creando una piccola scorciatoia per modificare dinamicamente molte proprietà di più elementi del dom contemporaneamente. L'idea è quella di utilizzare una sintassi abbreviata. Avrei potuto fare come fa jQuery, con una sintassi del tipo selettore(".classe").applicaProprieta({altezza: qualcosa, larghezza: qualcosa, etc. etc}), ma mi sembrava un inutile spreco di oggetti e di cicli. Così sono arrivato a una sintassi del tipo selettore(".classe").applicaProprieta(altezza, qualcosa)(larghezza, qualcosa)(etc. etc.).
    Ne è venuto fuori questo abbozzo, che sembrerebbe funzionare abbastanza bene:

    codice:
    <!doctype html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Esempio</title>
    <script type="text/javascript">
    // "use strict";
    
    function setStyles (sProp, sVal) {
    	for (var nEl = 0, nLen = this.nodes.length; nEl < nLen; this.nodes[nEl].style[sProp] = sVal, nEl++);
    	this.follow = setStyles;
    	return this;
    }
    
    function setAttribs (sAttrib, sVal) {
    	for (var nEl = 0, nLen = this.nodes.length; nEl < nLen; this.nodes[nEl][sAttrib] = sVal, nEl++);
    	this.follow = setAttribs;
    	return this;
    }
    
    function getSelectors () { return this.selectors; };
    
    function getNodes () { return this.nodes; };
    
    function domQuery (sSelectors) {
    	var oQuery = new Function("return arguments.callee.follow.apply(arguments.callee, arguments);");
    	oQuery.selectors = sSelectors;
    	oQuery.nodes = document.querySelectorAll(sSelectors);
    	oQuery.attributes = setAttribs;
    	oQuery.inlineStyle = setStyles;
    	oQuery.follow = getNodes;
    	oQuery.toString = getSelectors;
    	oQuery.valueOf = getNodes;
    	return oQuery;
    }
    </script>
    </head>
    
    <body>
    
    <div class="testClass">Lorem ipsum</div>
    
    
    Testo di prova</p>
    <div class="testClass">dolor sit amet</div>
    
    <script type="text/javascript">
    domQuery(".testClass").attributes("lang", "it")("title", "Testo di prova").inlineStyle("backgroundColor", "black")("color", "white")("width", "100px")("height", "50px");
    </script>
    </body>
    
    </html>
    Il problema però sorge nell'eventualità di renderlo modulare. Gli oggetti che creo contengono attualmente due metodi utili: oggetto.inlineStyle() e oggetto.attributes(), che vengono assegnati loro dalla funzione domQuery(). Immaginiamo di voler aggiungere un altro metodo: dovrei modificare la funzione domQuery() per contemplarlo.
    Quello che non riesco proprio a capire è se esiste un modo per assegnare un prototipo a questi miei oggetti di modo che modificando il prototipo a piacimento durante il caricamento della pagina decido quali metodi includere e quali no. Spero sia chiaro qual è il problema

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2010
    Messaggi
    3,660
    non credo sia possibile o almeno a me non viene in mente niente... se vuoi fare qualcosa di modulare penso che ti devi cmq appoggiare a qualche oggetto dove censisci i metodi da "supportare", e magari crearti una funzione che li aggiunga all'oggetto oQuery. Una bozza della prima cosa che mi viene in mente:

    codice:
    objQuery = {
    oggettoMetodi : {},
    domQuery : function (sSelectors) {
    	var oQuery = new Function("return arguments.callee.follow.apply(arguments.callee, arguments);");
    	
            for(method in oggettoMetodi){
                //aggiungo metodi all'oggetto oQuery
            }
    	return oQuery;
    },
    addMethodQuery : function(){
         //aggiungo metodo all'oggettoMetodi
    }
    }
    magari ci avevi già pensato ma volevi procedere in modo alternativo o magari non ho capito niente , vedi tu se puo esserti utile

  3. #3
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Sì ci avevo già pensato
    Mi chiedevo se fosse possibile fare qualcosa per cui potessi evitare il ciclo for(method in oggettoMetodi), ma evidentemente non ci si riesce...

    P.S. Lo sai che arguments.callee è deprecato e che se scompare dal linguaggio una cosa come quella che ho fatto io diventerebbe impossibile? Se t'interessa discuterne, ho aperto un bug qui: https://bugzilla.mozilla.org/show_bug.cgi?id=725398 e qui: https://bugs.ecmascript.org/show_bug.cgi?id=263 .
    Inoltre ho introdotto la questione qui: https://developer.mozilla.org/en/Jav...ents.callee.3F

    Ciao e grazie cmq ^^

  4. #4
    Utente di HTML.it
    Registrato dal
    Dec 2010
    Messaggi
    3,660
    potrebbe funzionare anche cosi, senza la creazione di nuovi metodi o oggetti di supporto:

    codice:
    domQuery = function (sSelectors) {
    	var oQuery = new Function("return arguments.callee.follow.apply(arguments.callee, arguments);");
    	oQuery.selectors = sSelectors;
    	oQuery.nodes = document.querySelectorAll(sSelectors);
    	oQuery.attributes = setAttribs;
    	oQuery.inlineStyle = setStyles;
    	oQuery.follow = getNodes;
    	oQuery.toString = getSelectors;
    	oQuery.valueOf = getNodes;
    	for(method in domQuery){
    		oQuery[method] = domQuery[method];
    	}
    	return oQuery;
    }
    
    domQuery.method1 = method1;
    domQuery.method2 = method2;
    Resta il fatto però che non si riesce a levare quel ciclo

    Lo sai che arguments.callee è deprecato e che se scompare dal linguaggio una cosa come quella che ho fatto io diventerebbe impossibile?
    No non ne sapevo nulla...

  5. #5
    P.S. Lo sai che arguments.callee è deprecato e che se scompare dal linguaggio una cosa come quella che ho fatto io diventerebbe impossibile?
    Per togliere il callee puoi closure-are oQuery:

    codice:
    var oQuery = function() {
      return oQuery.follow.apply(oQuery, arguments);
    };

  6. #6
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Eh, lo so... ma le closures cerco di evitarle come la peste... non è un caso che avevo scelto di creare le nuove funzioni tramite il costruttore di funzioni: le funzioni così create infatti non creano mai una closure col proprio contesto (se infatti provassi ad accedere a variabili locali dalle funzioni così create ti verrebbe restituito un errore).
    Semplicemente mi sembra folle che vogliano eliminare arguments.callee.
    Un'alternativa al costruttore di funzioni che non crei closures in questo caso potrebbe essere Function.bind(). Ma ciò non toglie il fatto che eliminare arguments.callee significherebbe privare le funzioni costruite tramite new Function della possibilità di riconoscere sé stesse. Mah.

  7. #7
    Originariamente inviato da carlomarx
    Eh, lo so... ma le closures cerco di evitarle come la peste... non è un caso che avevo scelto di creare le nuove funzioni tramite il costruttore di funzioni: le funzioni così create infatti non creano mai una closure col proprio contesto (se infatti provassi ad accedere a variabili locali dalle funzioni così create ti verrebbe restituito un errore).
    Semplicemente mi sembra folle che vogliano eliminare arguments.callee.
    Un'alternativa al costruttore di funzioni che non crei closures in questo caso potrebbe essere Function.bind(). Ma ciò non toglie il fatto che eliminare arguments.callee significherebbe privare le funzioni costruite tramite new Function della possibilità di riconoscere sé stesse. Mah.
    Sì, capisco il punto di vista su entrambe le questioni...tornando al problema iniziale, ho una curiosità: cosa ti da fastidio nell'usare una sintassi più jquery-like on obj.literal e cicli?

    Per il consumo della memoria nell'istanziare i literal non credo ci siano grossi problemi, per il genere di lavoro a cui punti la loro dimensione è relativamente piccola. Inoltre spesso c'è la necessità di utilizzare oggetti già pronti (ad esempio se ti vengono spediti dal server in notazione JSON, ma immagino ci siano moltri altri casi).
    In tal caso dovrei ciclare io sviluppatore sul mio oggetto per effettuare n chiamate alla function.
    Questo vorrebbe anche dire creare ogni volta l'ambiente locale e fare degli accessi in memoria n volte (ed esempio, con il ciclo accedo una volta a nodi.length, nella tua implementazione ci accedo n volte).

    Per quanto riguarda le "tempistiche" ho preparato un test su
    jsperf giusto per dare un'occhiata generica (scusa se ci sono errori, ho fatto un pò al volo). Nel mio caso ho usato un while che dovrebbe dare un minimo di vantaggio, il tuo codice non l'ho toccato invece.

    Pare che le due soluzioni siano paragonabili. Quella tipo jQuery è più veloce su IE però, un dettaglio interessante.
    Inoltre l'espressività della seconda soluzione mi pare migliore (ma questo è solo un parere personale).

    Sarebbe interessante, poi, controllare come i vari interpreti gestiscono lo stack delle chiamate per saperne di più.
    Ciò non toglie che il tuo codice abbia un certo stile e appeal, mi piace molto l'idea di ritornare la function ad ogni passo di calcolo.

    Fammi sapere cosa ne pensi.



  8. #8
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da antotan
    Sì, capisco il punto di vista su entrambe le questioni...tornando al problema iniziale, ho una curiosità: cosa ti da fastidio nell'usare una sintassi più jquery-like on obj.literal e cicli?
    Niente, è solo che... perché devo creare un oggetto ogni volta (tra l'altro consumando anche qualche carattere in più) se posso evitare? Calcola anche che un oggetto una volta creato non viene più eliminato, resta freezato nella memoria ram. È una questione di stile


    Originariamente inviato da antotan
    Per il consumo della memoria nell'istanziare i literal non credo ci siano grossi problemi, per il genere di lavoro a cui punti la loro dimensione è relativamente piccola. Inoltre spesso c'è la necessità di utilizzare oggetti già pronti (ad esempio se ti vengono spediti dal server in notazione JSON, ma immagino ci siano moltri altri casi).
    In tal caso dovrei ciclare io sviluppatore sul mio oggetto per effettuare n chiamate alla function.
    Questo vorrebbe anche dire creare ogni volta l'ambiente locale e fare degli accessi in memoria n volte (ed esempio, con il ciclo accedo una volta a nodi.length, nella tua implementazione ci accedo n volte).
    Nulla vieta la creazione di un nuovo metodo chiamato, che so, attributesFromObj(), che funzioni jQuery-like solo ed esclusivamente per quei casi in cui ti trovi a lavorare con oggetti già pronti. Ma nella stragrande maggioranza dei casi ti trovi a dover lavorare con proprietà da settare manualmente. E a quel punto creare oggetti in più è perfettamente inutile.
    Su nodi.length hai ragione... ma è anche vero che se non sbaglio i cicli con l'operatore "in" sono più dispendiosi (prova tu stesso: crea un array con x elementi e fai partire un ciclo su di esso prima nel modo tradizionale e poi con l'operatore in).


    Originariamente inviato da antotan
    Per quanto riguarda le "tempistiche" ho preparato un test su
    jsperf giusto per dare un'occhiata generica (scusa se ci sono errori, ho fatto un pò al volo). Nel mio caso ho usato un while che dovrebbe dare un minimo di vantaggio, il tuo codice non l'ho toccato invece.

    Pare che le due soluzioni siano paragonabili. Quella tipo jQuery è più veloce su IE però, un dettaglio interessante.
    Inoltre l'espressività della seconda soluzione mi pare migliore (ma questo è solo un parere personale).
    Che intendi per "espressività"?


    Originariamente inviato da antotan
    Ciò non toglie che il tuo codice abbia un certo stile e appeal, mi piace molto l'idea di ritornare la function ad ogni passo di calcolo.

    Fammi sapere cosa ne pensi.
    Carina l'idea della comparazione
    Il punto principale di quel codice è il fatto che ogni metodo dell'oggetto x ti restituisce l'oggetto x stesso, dimodoché puoi evitare di citarlo ogni volta: oggettoX.faiQualcosa().faiQualcosaltro().etc().etc ().
    Che poi l'oggetto x sia anche eseguibile è un dettaglio in più, che ti permette di non dover ripetere ogni volta l'ultima azione eseguita: oggettoX.faiQualcosa()()().faiQualcosaltro().etc() ()()().etc().
    Come ti ho già accennato, è un modo per abbreviare il codice scritto a mano. Che poi sia leggerissimamente anche più performante è una cosa che non guasta... Ma se avessi a che fare con oggetti già pronti che descrivessero le proprietà da assegnare stai sicuro che creerei un altro metodo ad hoc jQuery-like.

  9. #9
    Originariamente inviato da carlomarx
    Niente, è solo che... perché devo creare un oggetto ogni volta (tra l'altro consumando anche qualche carattere in più) se posso evitare? Calcola anche che un oggetto una volta creato non viene più eliminato, resta freezato nella memoria ram. È una questione di stile
    Forse mi sfugge qualcosa, ma quegli oggetti vengono "spazzolati" appena passa il gc, se non hanno più riferimenti.


    Nulla vieta la creazione di un nuovo metodo chiamato, che so, attributesFromObj(), che funzioni jQuery-like solo ed esclusivamente per quei casi in cui ti trovi a lavorare con oggetti già pronti. Ma nella stragrande maggioranza dei casi ti trovi a dover lavorare con proprietà da settare manualmente. E a quel punto creare oggetti in più è perfettamente inutile.
    Su nodi.length hai ragione... ma è anche vero che se non sbaglio i cicli con l'operatore "in" sono più dispendiosi (prova tu stesso: crea un array con x elementi e fai partire un ciclo su di esso prima nel modo tradizionale e poi con l'operatore in).
    Si, ovvio. Però è un pò riduttivo come scenario, spesso ne setti più di una come proprietà. Poi ovviamente è dura dire chi fa prima tra il for-in e le n gestioni del call-stack+accessi.

    Che intendi per "espressività"?
    Intendevo "si legge meglio". Ripeto, è solo un parere personale.


    Carina l'idea della comparazione
    Il punto principale di quel codice è il fatto che ogni metodo dell'oggetto x ti restituisce l'oggetto x stesso, dimodoché puoi evitare di citarlo ogni volta: oggettoX.faiQualcosa().faiQualcosaltro().etc().etc ().
    Che poi l'oggetto x sia anche eseguibile è un dettaglio in più, che ti permette di non dover ripetere ogni volta l'ultima azione eseguita: oggettoX.faiQualcosa()()().faiQualcosaltro().etc() ()()().etc().
    Come ti ho già accennato, è un modo per abbreviare il codice scritto a mano. Che poi sia leggerissimamente anche più performante è una cosa che non guasta... Ma se avessi a che fare con oggetti già pronti che descrivessero le proprietà da assegnare stai sicuro che creerei un altro metodo ad hoc jQuery-like.
    tutto chiaro, non ho più curiosità allora

  10. #10
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da antotan
    Forse mi sfugge qualcosa, ma quegli oggetti vengono "spazzolati" appena passa il gc, se non hanno più riferimenti.
    Forse potrei sbagliarmi, ma dalle ricerche che avevo fatto qualche tempo fa avevo capito che al passaggio del garbage collector gli oggetti e le funzioni senza più riferimenti, a differenza dei valori primitivi (stringhe, numeri e booleani, che in effetti vengono rimossi a tutti gli effetti), vengono solo freezate. Ma a questo punto siamo al filosofico


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.