PDA

View Full Version : [javascript] oggetti


DNAx86
13-09-2010, 16:55
Sto utilizzando da poco gli oggetti in javascript
E ho notato che dopo aver impostato il valore di una variabile nel costruttore,
i metodi dello stesso oggetto che ho aggiunto al prototipo dello stesso oggetto
non possono accedere a tali valori, risulta undefined.

ES:

function ContexAdmin() {
this.URL = "XXX";
}
ContexAdmin.prototype.handleInsertContex = function(event) {
alert(this.URL);
}

alert stampa a video "undefined" invece che "XXX"


Come mai?

DNAx86
14-09-2010, 07:55
Qualche idea sul perché I metodi non accedono ai valori ?
Nb: conosco bene la programmazione ad oggetti tradizionale.

dojolab
14-09-2010, 08:02
Qualche idea sul perché I metodi non accedono ai valori ?
Nb: conosco bene la programmazione ad oggetti tradizionale.

Non amo JS e non considero JS un linguaggio ad Oggetti (nonostante molti lo spacciano come tale :P); ma questa è una opinione strettamente personale.

Le variabili sono tutte LOCALI, ovvero se definite dentro una determinata funzione, hanno valore solo in essa.

Nel tuo esempio URL è stata definita nella funzione ContextAdmin() { e potrà essere usata SOLO li dentro. L'alternativa che puoi fare è far ritornare a ContextAdmin il valore e richiamare la funzione nell'altro"oggetto" JS.

DNAx86
14-09-2010, 09:57
Non amo JS e non considero JS un linguaggio ad Oggetti (nonostante molti lo spacciano come tale :P); ma questa è una opinione strettamente personale.

Le variabili sono tutte LOCALI, ovvero se definite dentro una determinata funzione, hanno valore solo in essa.

Nel tuo esempio URL è stata definita nella funzione ContextAdmin() { e potrà essere usata SOLO li dentro. L'alternativa che puoi fare è far ritornare a ContextAdmin il valore e richiamare la funzione nell'altro"oggetto" JS.

Sapevo già di molte cose strane sul modo in cui js gestisce gli oggetti,
Ma dopo quello che mi hai detto sono rimasto shoccato.

Ad ogni modo, quello che hai detto vale anche nelle variabili impostate nel costruttore?
Perché nel mio esempio ContexAdmin() è il costruttore.

Aggiungo poi che il libro dove ho studiato js mostra esempi simili al mio dove pero il metodo handleInsertContex() riesce magicamente ad accedere ai valori impostati nel costruttore.
È il libro che sbaglia o sono io?

shinya
14-09-2010, 10:10
Umh... ma come istanzi l'oggetto?

Non sono un ninja in javascript, ma questo a me funziona per esempio (appena provato su chrome):

function MyObject() {
this.x = 42;
}

MyObject.prototype.testFunction = function() {
alert(this.x);
}

var obj = new MyObject();
obj.testFunction();

DNAx86
14-09-2010, 10:26
Umh... ma come istanzi l'oggetto?

Non sono un ninja in javascript, ma questo a me funziona per esempio (appena provato su chrome):

function MyObject() {
this.x = 42;
}

MyObject.prototype.testFunction = function() {
alert(this.x);
}

var obj = new MyObject();
obj.testFunction();


Cosi:
var contexAdminObj = new ContexAdmin();
var ic = document.getElementById("ic");
ic.addEventListener("click", contexAdminObj.handleInsertContex, true);

inpratica quel metodo dell'oggetto in questione è un handler di un evento.
è sbagliata la logica?

è meglio che creo un oggetto il cui costruttore è l'handler (tipo java) ?

PS: l'alert funziona se chiamo contexAdminObj.handleInsertContex() direttamente, senza assegnarla all'evento

dojolab
14-09-2010, 10:32
Sapevo già di molte cose strane sul modo in cui js gestisce gli oggetti,
Ma dopo quello che mi hai detto sono rimasto shoccato.

Ad ogni modo, quello che hai detto vale anche nelle variabili impostate nel costruttore?
Perché nel mio esempio ContexAdmin() è il costruttore.

Aggiungo poi che il libro dove ho studiato js mostra esempi simili al mio dove pero il metodo handleInsertContex() riesce magicamente ad accedere ai valori impostati nel costruttore.
È il libro che sbaglia o sono io?

Perdonami, mi era sfuggito il "this." prima di URL :rolleyes:, troppo presto sul Forum :P

Se inizializzi l'oggetto dovrebbe funzionare come ha fatto shinya.

handleInsertContex

Sarebbe? :|
Se è un metodo mancano le () :|

Se è un attributo lascio perdere e ritiro le due righe sopra scritte ;)

DNAx86
14-09-2010, 10:43
Se è un metodo mancano le () :|

Se è un attributo lascio perdere e ritiro le due righe sopra scritte ;)[/QUOTE]

Si è un metodo però so che è giusto registrare un handler dentro addeventlistener senza scrivere le parentesi, questo perchè è una assegnamento di una funzione non è la chiamata di una funzione.
La funzione è chiamata quando ci sarà l'evento.

Tutto il problema è sorto nel mixare oggetti con hanler di eventi.
Ora tra i vostri consigli e una rilettura del mio libro ho capito:

cosi funziona:
ic.addEventListener("click",
function(event){ contexAdminObj.handleInsertContex(event); },
true);

Quindi ho risolto

dojolab
14-09-2010, 10:47
cosi funziona:
ic.addEventListener("click",
function(event){ contexAdminObj.handleInsertContex(event); },
true);

Quindi ho risolto

Mio dio, chi ha inventato questo linguaggio andrebbe preso e fucilato, insieme a Cox :| (IMHO).

Metti risolto nel titolo ;)

DNAx86
14-09-2010, 10:59
Mio dio, chi ha inventato questo linguaggio andrebbe preso e fucilato, insieme a Cox :| (IMHO).

Metti risolto nel titolo ;)

è la prima cosa che ho pensato quando ho letto il capitolo sulle classi e sugli eventi :D

[OT]: Riguardo al titolo, come si fà la modifica al titolo di un thread in questo forum? Non vedo l'opzione

dojolab
14-09-2010, 11:08
è la prima cosa che ho pensato quando ho letto il capitolo sulle classi e sugli eventi :D

[OT]: Riguardo al titolo, come si fà la modifica al titolo di un thread in questo forum? Non vedo l'opzione

Dopo un pò che è aperto non si può, me lo dimentico sempre :D (provenendo da altre Community mi scordo questa cosa :|)

MEMon
14-09-2010, 14:15
Il problema l'hai beccato da solo, ovvero dando la funzione all'event listener viene chiamata in un altro contesto, più precisamente il contesto passa dal tuo oggetto a "window". (per contesto intendo lo scope delle variabili, il significato di "this").

Quello che hai effettuato tu si chiama closure, guardatele subito e ti si aprirà un magico mondo.
Senza saper usare le closure non si può dire davvero di usare javascript.


ps. javascript è ad oggetti, ma di tipo prototipale, basato sugli oggetti e non sulle classi. :p

dojolab
14-09-2010, 17:59
ps. javascript è ad oggetti, ma di tipo prototipale, basato sugli oggetti e non sulle classi. :p

Io e JS abbiamo divorziato anni fa :D

shinya
15-09-2010, 09:58
Io e JS abbiamo divorziato anni fa :D
Guarda che non è poi cosi brutto come sembra... se poi usi librerie tipo mootools puoi scrivere codice piuttosto strutturato facilmente.
Prova anche a dare un'occhiata a Javascript: The Good Parts di Crockford :P

dojolab
15-09-2010, 10:07
Guarda che non è poi cosi brutto come sembra... se poi usi librerie tipo mootools puoi scrivere codice piuttosto strutturato facilmente.
Prova anche a dare un'occhiata a Javascript: The Good Parts di Crockford :P

Uso JQuery tutti i giorni.
Anni fa usavo mootools.

Questo non ha fatto altro che accelerare il mio divorzio nei confronti di questo linguaggio :D

astorcas
15-09-2010, 10:26
Povero javascript.... secondo me il vostro problema è... che è javaSCRIPT... :asd:

dojolab
15-09-2010, 10:42
Povero javascript.... secondo me il vostro problema è... che è javaSCRIPT... :asd:

O forse JAVAscript? :D
Sarà il nome? :P

marco.r
15-09-2010, 19:11
Mio dio, chi ha inventato questo linguaggio andrebbe preso e fucilato, insieme a Cox :| (IMHO).

Metti risolto nel titolo ;)

Javascript diventa molto piu' semplice se si smette di pensarlo come un linguaggio ad oggetti, e lo si usa come quello che e' in realta', ovvero un linguaggio funzionale con del malpensato zucchero sintattico per farlo sembrare ad oggetti.
Magicamente spariscono un sacco di comportamenti strani e illogici.
(poi la sintassi ci mette del suo, ma almeno la semantica diventa molto piu' pulita)

MEMon
15-09-2010, 19:15
Javascript diventa molto piu' semplice se si smette di pensarlo come un linguaggio ad oggetti, e lo si usa come quello che e' in realta', ovvero un linguaggio funzionale con del malpensato zucchero sintattico per farlo sembrare ad oggetti.
Magicamente spariscono un sacco di comportamenti strani e illogici.
(poi la sintassi ci mette del suo, ma almeno la semantica diventa molto piu' pulita)

Rabbrividisco a quello che hai appena scritto, posso? :D :asd:


Javascript è moooolto malleabile, impone poca roba, ci si fa di tutto e in tutti i modi, è questo forse che spaventa un pò.
E' "plastico" diciamo.

Javascript comunque è fortemente ad oggetti, ma non lo dovete associare ai linguaggi OO che conoscete, non è basato sulle classi, non c'è quindi il concetto di classe, variabili private, incapsulamento, super classe, ereditarietà a classi ecc ecc.
E' di tipo prototipale, quindi totalmente diverso come concezione.

Posso assicurare comunque, che una volta imparato ad usarlo e a "domarlo" lo si ama da quanto è stupendamente "logico".

marco.r
16-09-2010, 22:24
E' di tipo prototipale, quindi totalmente diverso come concezione.

Il fatto che sia prototipale non giustifica comportamenti strani come quello segnalato in questo thread. Perche' la chiamata

obj.method()

da un risultato diverso da

x = obj.method
x();

?
Se uno si accorge gli oggetti (e tutto il resto) non sono altro che hash-table,
che i metodi sono in realta' funzioni, che this e'il top di uno stack aggiornato in alcune condizioni particolari, tutto diventa piu' logico e semplice da capire

MEMon
16-09-2010, 22:28
Semplicemente l'event handler cambia lo scope del metodo, in javascript si può facilmente "staccare" un metodo da un oggetto ed usarlo con un altro scope.

Ogni metodo è una Function, che è un oggetto con particolari metodi e proprietà, tra questi metodi ve ne sono due call e apply, che permettono di cambiare lo scope dell'oggetto "Function".
L'event handler fa questo diciamo. Niente di strano se si sa.


edit. dimenticavo, nel tuo esempio da un significato diverso perché stai usando la funzione in un contesto diverso, che è "window".
Infatti x non fa parte di obj, ma fa parte di window(tutte le variabili globali lo sono), e per forza di cose il contesto diventa window.
E' proprio in questi casi che si utilizzano le closure, che è LA CARATTERISTICA, e il punto di forza, di questo linguaggio.

function MyObject(){
this.test="PROVA";
}
MyObject.prototype.method=function(){
alert(this);
alert(this.test);
}

var obj=new MyObject();

var x=obj.method;
var y=function(){
alert(this);
obj.method();
}

x(); // alert [window] -> undefined
y(); // alert [window] -> [MyObject] -> "PROVA"

// Controprova
obj.z=obj.method;
z(); // alert [MyObject] -> "PROVA"

// z fa parte di MyObject e non di Window

Tutto molto logico a parer mio.