2009-12-31 27 views
6

Solo por las patadas que estoy tratando de crear un objeto de datos simple en javascript. Aquí está el código.Creación de objetos en 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); 

Hay pocas preguntas que tengo sobre esta creación.

  1. Quiero crear un objeto donde las propiedades/atributos del objeto sean privadas y no visibles para el mundo. ¿Tengo éxito en hacer eso? ¿Realmente no puedo acceder a los atributos del objeto?
  2. ¿Existe alguna forma mejor de crear este tipo de objeto?
  3. Si quiero heredar este objeto, debería hacer un newObject.prototype = roverObject ¿funcionará? Y eso tiene sentido más que nada.
  4. Finalmente tengo un problema raro. Observe el último método del objeto "where" que devuelve una cadena concatenada. Aquí traté de seguir el código en su lugar.

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

y luego hizo un siguiente

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

arrojó siguiente error console.log para mí:

cannot access optimized closure 

¿Por qué dice eso? ¿Qué estoy haciendo mal?

Gracias por la ayuda. ¡Cualquier comentario de revisión sería apreciado también! Cheers

+2

olvidó punto y coma en 'newRover var = {}' y en todas sus definiciones de funciones. – philfreo

+0

gracias. Hará ese cambio. :) – Priyank

+0

Agregar punto y coma no resolverá el problema aunque – Priyank

Respuesta

6

¿Tengo éxito en hacer eso? ¿Realmente no puedo acceder a los atributos del objeto?

Indeed. No tiene atributos de objeto, tiene variables locales en la función roverObject. No se puede acceder a las variables locales desde afuera, solo desde las funciones dentro de la función roverObject que tienen un cierre sobre ellas.

Que llame roverObject como constructor, con new roverObject, es irrelevante, ya que está devolviendo un objeto diferente de la función. Diciendo var rover1= roverObject() sin el new haría exactamente lo mismo.Notablemente, el objeto devuelto por [new] roverObject es un Object simple como lo creó desde {}; rover1 instanceof roverObject es false.

Si quería instanceof a trabajar, que tendría que llamar con new, y utilizar en lugar de thisnewRover en la función constructora.

Si deseo heredar este objeto, debería hacer un nuevo Objeto.prototipo = roverObject ¿funcionará? Y eso tiene sentido más que nada.

No. Actualmente no tiene en cuenta la creación de prototipos. Está utilizando una copia separada de cada método para cada instancia del roverObject. Sin duda puede hacer objetos de esta manera, pero es un enfoque diferente al de creación de prototipos. Si quería hacer algo así como una subclase de roverObject en la disposición que tiene ahora, que diría algo así como:

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

Nota ya que las variables locales 'privado' en el constructor de la clase base en realidad privada, incluso la subclase no puede llegar a ellos. No hay 'protegido'.

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

¿Qué está tratando de hacer? No puedo entender el error que haces; todo lo anterior hace es asignar la cadena con la ubicación a where (antes de que se hayan llamado los métodos del colocador, por lo que está lleno de indefinidos).

¿Existe alguna forma mejor de crear este tipo de objeto?

Quizás. ver this question para una discusión de las estrategias de clase/instancia en JavaScript.

+0

excelente puntero! Proporcionó toneladas de información. Gracias – Priyank

1

Con respecto a 4. - está intentando registrar la función, no el resultado de llamar a la función. Debería ser console.log(rover1.where()); My guess firebug (supongo que es console.log de firebug) no le gusta registrar definiciones de funciones.

EDIT Oh, entiendo, en realidad estás ejecutando la función where cuando asignas rover.where. ¿Estás tratando de conseguir que lo que parece una propiedad sea realmente una función? Si ese es el caso, no funcionará. Tendrá que ser una función si quieres que se evalúe cuando se llame.

Lo que sucede en su caso where se ejecuta en la función de constructor. En ese momento, aún está creando el cierre roverObject y, por lo tanto, es demasiado pronto para acceder a sus variables privadas.

+0

que no funciona. Estoy seguro, si piensas si mi función de cierre devuelve el valor de la función donde, en lugar de la función en sí, ¿dónde se convierte en un atributo correcto? No es una función – Priyank

+0

Correcto, pero cuando llamas a 'console.log (rover1.where)', estás tratando de imprimir la definición de la función, que supongo que Firebug no puede (en este caso) –

+0

Ver edición, no me di cuenta de la nueva sintaxis para la función 'where' :) –

0

Esto es solo abordar el punto 1 de su publicación.

He aquí un buen artículo sobre Javascript miembros privados y más:
Private Members in JavaScript

2

P1: puede crear miembros 'privado' en 'clases' de javascript. En javascript, la privacidad no está determinada por ningún especificador de acceso. En cambio, el acceso debe estar específicamente instrumentado. Ejemplo:

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; 
    } 
} 

ámbito de los objetos en javascript se rige por un concepto raro llamado cierres. AFAIK, no existe un concepto paralelo en ningún otro lenguaje popular como C +/Java, etc.

Aunque entiendo lo que son los cierres, no puedo expresarlo con palabras. Tal vez una demostración le ayudará a:

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

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

closureDemo(); 

ahora, mientras setDone se llama desde dentro doLater, todavía puede acceder done en closureDemo, a pesar de que no donees de alcance (en el sentido convencional del procedimiento).

Creo que entenderá más cuando lea this.


Q2: Solo puedo decir lo que hago; No sé si es mejor o no. Si escribiera su código, que se vería así:

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(); 

Puntos a tener en cuenta:

  1. capitalización de "nombre de la clase" 's primera letra
  2. uso de este lugar de roverObject
  3. esta función es un constructor puro. no devuelve nada

P3: si usted quiere hacer la herencia, a continuación, mi método (uso de este) no funcionará. En su lugar, los métodos públicos deben ser parte del prototype de RoverObject. Lee this. Excelente material.

Espero que ayude.


EDITAR: Existe un problema con la forma en que su código está funcionando. Problemas:

  1. su función no hace lo que su nombre sugiere. Su nombre debería ser createRoverObject, porque eso es exactamente lo que está haciendo. No funciona como un constructor de clase
  2. los métodos admitidos por su clase son parte del objeto, pero los miembros de datos no lo son. Si bien esto puede funcionar (y no lo es, como sugiere el problema de console.log()), no es una buena forma de implementar una clase en javascript. El problema aquí es de cierres. De nuevo, no puedo expresar cuál es el problema específicamente, pero puedo smell it.
0

Al definir su objeto de esta manera obtendrá miembros privados.

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();