2009-12-31 14 views
6

Solo per i calci sto cercando di creare un oggetto dati semplice in javascript. Ecco il codice.Creazione oggetto in javascript

var roverObject = function(){ 

     var newRover = {}; 
     var name; 
     var xCord; 
     var ycord; 
     var direction; 

     newRover.setName = function(newName) { 
      name = newName; 
     }; 

     newRover.getName = function() { 
      return name; 
     }; 

     newRover.setDirection = function(newDirection) { 
      direction = newDirection; 
     }; 

     newRover.getDirection = function() { 
      return direction; 
     }; 

     newRover.setXCord = function(newXCord) { 
      xCord = newXCord; 
     }; 

     newRover.getXCord = function() { 
      return xCord; 
     }; 

     newRover.setYCord = function(newYCord) { 
      yCord = newYCord; 
     }; 

     newRover.getYCord = function() { 
      return yCord; 
     }; 

     newRover.where = function(){ 
      return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
     }; 

     return newRover; 
    }; 


    rover1 = new roverObject(); 
    rover2 = new roverObject();  

    rover1.setName("Mars Rover"); 
    rover1.setDirection("NORTH"); 
    rover1.setXCord(2); 
    rover1.setYCord(2); 
    console.log(rover1.where()); 
    console.log(rover1); 

    rover2.setName("Moon Rover"); 
    rover2.setDirection("SOUTH");  
    rover2.setXCord(1); 
    rover2.setYCord(1);  
    console.log(rover2.where());   
    console.log(rover2); 

Ci sono alcune domande che ho intorno a questa creazione.

  1. Desidero creare un oggetto in cui le proprietà/gli attributi dell'oggetto sono privati ​​e non visibili al mondo. Sono riuscito a farlo? Posso davvero non accedere agli attributi dell'oggetto?
  2. C'è un modo migliore per creare questo tipo di oggetto?
  3. Se voglio ereditare questo oggetto, dovrei fare un newObject.prototype = roverObject funzionerà? E questo ha un senso soprattutto.
  4. Finalmente ho un problema strano. Si noti l'ultimo metodo di objet "dove" che restituisce una stringa concatenata. Qui ho provato il seguente codice invece.

     newRover.where = function(){ 
         return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
        }(); 
    

e poi ha fatto un seguito

console.log(rover1.where); 
console.log(rover2.where); 

gettò seguente errore console.log per me:

cannot access optimized closure 

perché dovrebbe dire che? Che cosa sto facendo di sbagliato?

Grazie per tutto l'aiuto. Anche i commenti di revisione saranno apprezzati! Cheers

+2

punto e virgola dimenticato su 'var newRover = {}' e su tutte le definizioni di funzione. – philfreo

+0

grazie. Farà quel cambiamento. :) – Priyank

+0

l'aggiunta di punto e virgola non risolverà comunque il problema, anche se lo – Priyank

risposta

6

Sono riuscito a farlo? Posso davvero non accedere agli attributi dell'oggetto?

Infatti. Non hai attributi oggetto, hai variabili locali nella funzione roverObject. Le variabili locali non sono accessibili dall'esterno, solo dalle funzioni all'interno della funzione roverObject che hanno una chiusura su di esse.

Che si chiami roverObject come costruttore, con new roverObject, è irrilevante, poiché si restituisce un oggetto diverso dalla funzione. Dire var rover1= roverObject() senza il new farebbe esattamente la stessa cosa.In particolare l'oggetto restituito da [new] roverObject è un semplice Object come lo hai creato da {}; rover1 instanceof roverObject è false.

Se si voleva instanceof a lavorare, si dovrebbe chiamare con new, e utilizzare this invece di newRover nella funzione di costruzione.

Se voglio ereditare questo oggetto, dovrei fare un nuovoObject.prototype = roverObject funzionerà? E questo ha un senso soprattutto.

No. Attualmente non è consentito il prototipo. Si sta utilizzando una copia separata di ciascun metodo per ciascuna istanza di roverObject. Puoi fare certamente degli oggetti in questo modo ma è un approccio diverso rispetto alla prototipazione. Se si voleva fare qualcosa di simile a una sottoclasse roverObject nella disposizione che hai ora, che avresti detto qualcosa del tipo:

function AdvancedRover() { 
    var rover= new roverObject(); 
    rover.doResearch= function() { 
     return rover.where()+' and is doing advanced research'; 
    }; 
    return rover; 
} 

nota poiché le variabili locali 'private' nel costruttore della classe base in realtà sono private, anche la sottoclasse non può ottenere da loro. Non c'è "protetto".

newRover.where = function() {...}();

Che cosa sta cercando di fare? Non riesco a ottenere l'errore che fai; tutto quanto sopra fa è assegnare la stringa con la posizione a where (prima che i metodi setter siano stati chiamati, quindi è pieno di indefiniti).

C'è un modo migliore per creare questo tipo di oggetto?

Forse. vedere this question per una discussione sulle strategie di classe/istanza in JavaScript.

+0

puntatore eccellente! Ha fornito un sacco di informazioni. Grazie – Priyank

1

Riguardo a 4. - si sta tentando di registrare la funzione, non il risultato della chiamata della funzione. Dovrebbe essere console.log(rover1.where()); La mia ipotesi firebug (presumo che sia console.log di firebug) non piace registrare le definizioni delle funzioni.

EDIT Oh ho capito, stai eseguendo la funzione where quando assegni rover.where. Stai cercando di ottenere quello che sembra una proprietà per essere effettivamente una funzione? Se questo è il caso, non funzionerà. Dovrà essere una funzione se vuoi che venga valutata quando viene chiamata.

Cosa succede nel tuo caso where viene eseguito nella funzione di costruzione. A quel punto si sta ancora creando la chiusura roverObject e quindi è troppo presto per accedere alle sue variabili private.

+0

che non funziona. Sono sicuro, se pensi che la mia funzione di chiusura restituisca il valore della funzione dove, invece della funzione stessa, dove diventa un attributo giusto? Non una funzione – Priyank

+0

Corretto - ma quando si chiama 'console.log (rover1.where)', si sta tentando di stampare la definizione della funzione, che presumo che Firebug non possa (in questo caso) –

+0

Vedere modifica, non ho realizzato il nuovo sintassi per la funzione 'where' :) –

0

Questo è solo l'indirizzo del punto 1 del tuo post.

Ecco un buon articolo su javascript soci privati ​​e di più:
Private Members in JavaScript

2

Q1: è possibile creare i membri 'private' in 'classi' JavaScript. In javascript, la privacy non è determinata da alcun identificatore di accesso. Invece, l'accesso deve essere specificamente strumentato. Esempio:

function MyClass() { 
    this.val = 100; // public; 
    var privateVal = 200; 

    function getVal() { return this.val; } // private method; 
    this.getPrivateVal = function() { // public method, accessor to private variable 
     return privateVal; 
    } 
} 

Lo scopo dell'oggetto in javascript è regolato da un concetto queer chiamato chiusure. AFAIK, non esiste un concetto parallelo in nessun altro popolare testo come C +/Java, ecc.

Mentre capisco cosa sono le chiusure, non posso metterlo in parole. Forse una dimostrazione vi aiuterà a:

function closureDemo() { 
    var done=false; 
    function setDone() { done=true; } 
    doLater(setDone); 
} 

function doLater(func) { setTimeout(func,1000); } 

closureDemo(); 

ora, mentre setDone viene chiamato dall'interno doLater, può comunque accedere a done closureDemo, anche se non doneè portata (nel senso procedurale convenzionale).

Penso che capirai di più quando leggi this.


Q2: Posso solo dire quello che faccio; Non so se sia meglio o meno. Se ho scritto il codice, sarebbe simile a questa:

function RoverObject() { 

    var newRover = {}; // privates 
    var name; 
    var xCord; 
    var ycord; 
    var direction; 

    this.setName = function(newName) { 
     name = newName; 
    }; 

    this.getName = function() { 
     return name; 
    }; 

    this.setDirection = function(newDirection) { 
     direction = newDirection; 
    }; 

    // and so on... 

    this.where = function(){ 
     return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
    }; 
} 
var rover1 = new RoverObject(); 

Punti da notare:

  1. capitalizzazione di "nome di classe" 's prima lettera
  2. uso di questo invece di roverObject
  3. questa funzione è un puro costruttore. non restituisce nulla.

Q3: se si vuole fare l'ereditarietà, quindi il mio metodo (uso di questo) non funzionerà. Invece, i metodi pubblici dovrebbero far parte dello prototype di RoverObject. Leggi this. Materiale eccellente

Spero che questo aiuti.


MODIFICA: c'è un problema con il modo in cui il codice sta funzionando. Problemi:

  1. la tua funzione non fa quello che suggerisce il nome. Il suo nome sarebbe stato meglio createRoverObject, perché è esattamente quello che sta facendo. Non funziona come un costruttore di classi
  2. i metodi supportati dalla classe fanno parte dell'oggetto, ma i membri dati non lo sono. Anche se questo potrebbe funzionare (e non lo è, come suggerisce il tuo problema console.log()), non è un buon modo per implementare una classe in javascript. Il problema qui è di chiusure. Ancora una volta, non sono in grado di articolare il problema in modo specifico, ma posso smell it.
0

Definire il tuo oggetto come questo ti dà membri privati.

function RolloverObject() { 
    var name; 
    var xCord; 
    var ycord; 
    var direction; 

    this.setName = function(newName) { name = newName; }; 
    this.getName = function() { return name; }; 

    this.setDirection = function(newDirection) { direction = newDirection; }; 
    this.getDirection = function() { return direction; }; 

    this.setXCord = function(newXCord) { xCord = newXCord; }; 
    this.getXCord = function() { return xCord; }; 

    this.setYCord = function(newYCord) { yCord = newYCord; }; 
    this.getYCord = function() { return yCord; }; 

    this.where = function() { 
     return "Rover :: " + name + " is at Location(" + xCord + "," + yCord + ") pointing to " + direction; 
    }; 
} 

var rolloverObject = new RolloverObject();