He creado un objeto con mas objetos dentro, pero no consigo acceder al valor de uno de los objetos para poder trabajar con ellos.
Necesito saber qué opción se ha seleccionado para poder trabajar con ella. He conseguido obtener el valor seleccionado (select/option), pero no consigo compararlo para poder seguir trabajando con él.
Hola! Varias cosas: 1. A qué "valor"? quieres acceder? Las variables de tipo no referenciado que pertenecen a un objeto se llaman propiedades. Los literales que pertenencen a un objeto también.
Por otro lado las funciones que pertenencen a objetos se llaman métodos.
Para acceder a la propiedad o método de un objeto, necesitas una referencia al objeto y utilizar el operador punto . o los corchetes del array.
Código
var titul ="titul";
alert(Peliculas6.titulo);
alert(Peliculas6["titulo"]);
alert(Peliculas6[titul+"o"]);
Son las 3 lo mismo, hay bastantes más pero para usos concretos. Puedes usar la última para cuando necesitas recorrer propiedades.
2. Por seguridad debes separar los códigos javascript de los códigos html poniéndolos en archivos separados. También debes añadir una CSP preferiblemente editando las cabeceras del servidor en la respuesta HTTP al cliente (u opcionalmente/adicionalmente usar la meta tag para lo mismo) para todos los recursos externos, javascript, librerías, php, css... Y bloquear el inline javascript en tus documentos HTML. No es la panacea de nada, pero si una buena práctica. También substituir varios caracteres que no quieras interpretar por las entidades HTML correspondientes a dicho caracter.
En concreto en tu código usas el onclick directamente dentro de un atributo de una etiqueta HTML. Remplázalo por obtener el elemento y añadirle un escuchador de eventos.
Código
var bttnAlq = document.getElementById("alquilar");
Puedes hacer encadenamiento de métodos si quieres.
3. No es necesario que añadas un id a cada etiqueta HTML para poder obtener el elemento con el getElementById o para poder aplicarle estilos en el CSS. Puedes usar el querySelector() y el querySelectorAll(). Le pasas como argumento el mismo selector que usarías en CSS. Por ejemplo para una etiqueta usas el nombre de la etiqueta sin más. Para classes usas el punto . . Para ids usas el hash #. Para atributos usas los corchetes [ ], escapas caracteres inválidos con \ etc. Tienes un tuto sencillo en la web de w3schools. Si buscas por google te sale. También tienes otros como
Te lo pongo con encadenamiento de metodos para que lo veas.
4. Para acceder a las opciones del select puedes usar ids o recorrer todas las opciones.
5. Puedes citar mi mensaje en el foro para ver lo que escribí para colorear el código. Puedes escribir las etiquetas a mano. O puedes seleccionar todo el código y darle al select que pone Código Geshi.
Por cierto creaste el tema en Dudas Generales. Los temas de javascript suelen publicarse bajo el foro de programación web, aunque el javascript no esté relacionado con el desarrollo web ya que no hay un foro específico para javascript.
« Última modificación: 13 Febrero 2020, 23:04 pm por @XSStringManolo »
En línea
Mi perfil de patrocinadores de GitHub está activo! Puedes patrocinarme para apoyar mi trabajo de código abierto 💖
Antes de nada, mil gracias por responder y por hacerlo tan claro y bien !! Sobre lo del foro de programación, ya vi que existía, pero al no ver javascript me fui a éste, para futuras ocasiones lo tendré en cuenta.
He utilizado el escuchador de eventos como me sugeriste y genial. Te cuento lo que quería hacer: al seleccionar una opción del Select, quería recorrer todo el objeto "Peliculas" y comparar el valor seleccionado, para saber donde se encuentra y poder manipularlo. Al hacer el bucle para comparar datos, me dice que: Cannot read property 'titulo' of undefined
- Esa metodología de creación de Objetos en javascript la vi en un antiguo video de JonMircha (2014):
- Tienes que reforzar tus bases teóricas, tu Función Peliculas que estás usando como "clase" es una plantilla para crear Objetos, NO es un Objeto en sí y no deberías de utilizarlo para nada más que para crear o instanciar Objetos como lo vienes haciendo con Peliculas1, Peliculas2, etc, estos si son Objetos y tienen propiedades (atributos) a los que puedes hacer referencia o acceder.
- Hay varios métodos para crear Objetos en javascript, dependerá más que nada de la versión dominante en el momento o de los gustos de cada quién.
- En tu caso tienes Objetos a un solo nivel y no "Un Objeto con más Objetos dentro", sin hacer muchos cambios a tu código, yo agruparía todos los Objetos Peliculas a un Array para manipularlos a todos más fácilmente:
Código
function Peliculas(titulo, año, duracion, precio, alquilada, ultimoUsuario){
this.titulo= titulo;
this.año = año;
this.duracion= duracion;
this.precio= precio;
this.alquilada= alquilada;
this.ultimoUsuario= ultimoUsuario;
};
var Peliculas1 =new Peliculas("The one",1989,1.50,"3 €",false,"");
var Peliculas2 =new Peliculas("The two",2005,2.50,"6 €",false,"");
var Peliculas3 =new Peliculas("The tree",2000,2.00,"5 €",false,"");
var Peliculas4 =new Peliculas("The four",2018,1.40,"6 €",false,"");
var Peliculas5 =new Peliculas("The five",1981,1.38,"3 €",false,"");
var Peliculas6 =new Peliculas("The six",2017,2.20,"4 €",false,"");
var Peliculas7 =new Peliculas("The seven",2005,1.50,"4 €",false,"");
- Tienes que reforzar tus bases teóricas, tu Función Peliculas que estás usando como "clase" es una plantilla para crear Objetos, NO es un Objeto en sí
Con el fin de no confundir está bien, pero las funciones si son objetos en javascript. Otra cosa es que la variable "Peliculas" contenga la función y que las otras variables "PeliculasN" contengan los objetos creados con la función.
Simplemente no puedes acceder a estos objetos usando un prefijo de las variables y tratar los números al final de las variables como si fueran propiedades de un objeto o arreglo.
Para empezar, el constructor está creando una película no una lista de películas, así que sería mejor que el constructor se llamara Película.
Código
function Pelicula(titulo, año, duracion, precio, alquilada, ultimoUsuario){
this.titulo= titulo;
this.año = año;
this.duracion= duracion;
this.precio= precio;
this.alquilada= alquilada;
this.ultimoUsuario= ultimoUsuario;
};
Si quieres tener un arreglo de Películas en la variable Películas puedes hacerlo así:
Código
var Peliculas =[
new Pelicula("The one",1989,1.50,"3 €",false,""),
new Pelicula("The two",2005,2.50,"6 €",false,""),
new Pelicula("The tree",2000,2.00,"5 €",false,""),
new Pelicula("The four",2018,1.40,"6 €",false,""),
new Pelicula("The five",1981,1.38,"3 €",false,""),
new Pelicula("The six",2017,2.20,"4 €",false,""),
new Pelicula("The seven",2005,1.50,"4 €",false,"")
Lo del escuchador de eventos es un fallo que se suele cometer. Debes asegurarte que el body está creado previamente cuando se ejecute tu código javascript. Puedes llevar todo el código (o la llamada al archivo) al final del body. O en su defecto escuchar el evento onload del body para llamar a tu javascript. Esto te permite añadir tu javascript en el head, aunque da un poco igual.
El error que tienes es porque estás intentando referenciar tu variable Peliculas1, Peliculas2, etc usando
Código
Peliculas[i]
. En realidad tu lo que quieres es formar las palabras "Peliculas1", "Peliculas2". No acceder como si fuese un array.
Es decir, cambia tu
Código
Peliculas[i]["titulo"]
por
Código
["Peliculas"+i]["titulo"]
o también te vale
Código
["Peliculas"+i].titulo
Otro fallo que veo, es que estás iterando desde 0. La primera referencia va a ser "Peliculas0" la cual no creaste. Entonces itera desde 1 y no desde 0.
Es decir, cambia tu bucle for de
Código
(i =0; i <= Peliculas.length; i++)
a
Código
(i =1; i < Peliculas.length;++i)
El comparador = te sobra porque se detecta el < primero de la forma en que iteras entonces nunca se evalua el condicional ==
Por otro lado, si no conoces el nombre de las claves: Por ejemplo, imagínate que dejas que el usuario añada sus claves valores. El usuario podría añadir a la Peliculas1 la clave "UltimaVezQueLaVi": "2018"; Entonces como trabajas tú con "UltimaVezQueLaVi" si tu no sabes de antemano que el usuario iba a añair exactamente esa propiedad?
Para este y otros casos. Te recomiendo usar Object.entries(elObjeto) para mostrar las propiedades y métodos enumerables de un objeto.
Qué es eso de enumerables o no enumerables? Los enumerables resumiendo muy muy mucho, son los que normalmente añades tú al objeto. Hay propiedades y métodos no enumerables en tu objeto, pero entiendo que no te interesa mostrarlos ni saber que existen. Practicamente todo en javascript son objetos (Funciones también aunque no se use el constructor, ejem ejem). Por ejemplo cuando creas una función, en realidad estás creando un objeto que tiene métodos no enumerables como el método
Código
[[call]]
que sirve para poder llamar a la función. Todo esto funciona a nivel interno, asique no te interesa demasiado. Te lo comento para que sepas lo que es un método nó enumerable por si tienes curiosidad y para mayor entendimiento. Estos los puedes mostrar también (de varias formas), modificarlos para ser enumerbles o hacer tus propias propiedades no enumerables. Incluso con strings o literales que no son objetos(tipos primitivos o no referenciados), cuando utilizas un método como .subString() a nivel interno se crea un wraper(envoltorio) sobre el literal creando un objeto temporal new String, asignándole el valor del literal, aplicándole el método subString() al nuevo objeto temporal string que creó el wraper, destruyendo el objeto String una vez se le aplicó el método subString(), length o cualquier otro, y retornándote el valor del método. Es decir, hasta lo que no es un objeto temporalmente puede que se usen objetos a nivel interno para proveerte acceso a métodos de tipos primitivos que en realidad no se le pueden aplicar métodos porque no son objetos y por lo tanto no tienen ningún método aplicable. Por eso se crea un objeto temporal que si tiene el método que intentas usar.
Para usar el Object.entries(), en navegadores modernos y actualizados, lo usas sin problemas. Pero es "relativamente nuevo".
Es decir, en navegadores no tan modernos, no existe el Object.entries(); Yo mismo estoy usando un navegador ahora mismo con motor javascript del 2015. (Samsung Internet Browser para Android)
Por qué hay gente como yo usando esto? Porque hay Smartphones y portátiles de baja gamma que no tienen suficiente espacio, procesador o ram para correr la última versión de Chrome. Hay otra gente que usa el navegador preinstalado en el teléfono y no sabe ni lo que es Chrome o un navegador, simplemente le dan al icono que pone internet, etc.
Como mínimo recomendable se debería dar soporte a ES6 (EcmaScript 6) que es una "versión" de javascript. Con eso deberías pasar de cubrir desde el 94-95% de navegadores actuales a el 97-98% de navegadores con javascript. Si quieres dar soporte al 99% de navegadores también le das soporte a ES5. Esto significa que no utilizas keywords que no existían de aquella.
Otra opción es dar soporte/incluir tú esas características no soportadas. Este concepto se conoce como polyfill. Te incluyo uno para Object.entries() de esta forma tu código funcionará sin problemas en navegadores antiguos.
Existe un programa que se llama babel. Es un "transpiler". Le metes tu código, la versión de javascript a la que quieres dar soporte y te genera el código equivalente para esa versión. No es perfecto, pero funciona bastante bien en muchos casos. Tiene versión online, busca por babeljs si te interesa.
No cambies el polyfill que te añadí, hay otros por ahí, pero no funcionan adecuadamente. Este lo testeé en ES5 y ES6.
Peliculas1.descripcion="Ambientado en el coliseo romano, Gladiator es una película ganadora de ...";
/* Obtener todas las propiedades enumerables de un objeto */
alert("TODO: \n\n"+ Object.entries(Peliculas1));
/* Obtener las propiedades en grupos valor/clave */
var propiedadesP1 = Object.entries(Peliculas1);
for(var i =0; i < propiedadesP1.length;++i)
alert("Clave/Valor número "+(1+i)+"\n\n"+ propiedadesP1[i])
/* Obtener solo las claves/referencias */
for(var i =0; i < propiedadesP1.length;++i)
alert("Esta es la propiedad enumerable número "+(i+1)+"\n\n"+ propiedadesP1[i][0])
/* Obtener solo los "valores" */
for(var i =0; i < propiedadesP1.length;++i)
alert("Esta es la data referenciada número "+(i+1)+"\n\n"+ propiedadesP1[i][1])
</script>
</body>
</html>
Aquí te hice ejemplos de como acceder a las distintas propiedades. Hay muchas más formas. Esta es bastante sencilla y compatible con ES5+ Si no te queda claro como va, ejecútalo y vas viendo que te imprime cada bucle y como accedo. Recuerda que el polyfill es para navegadores antiguos, a ti te va a ir incluso si lo borras, pero a otros con navegadores antiguos que ejecuten tu código no.
Si no acabas de comprender algo pregunta.
Te recomiendo el libro The principles of object-oriented javascript te explica con más detalle algunos de los conceptos básicos de los objetos en javascript.
« Última modificación: 14 Febrero 2020, 18:18 pm por @XSStringManolo »
En línea
Mi perfil de patrocinadores de GitHub está activo! Puedes patrocinarme para apoyar mi trabajo de código abierto 💖
Lo único que hace esto es crear un arreglo con un string "Peliculas1". No hace referencia a la variable "Peliculas1". Tendrías que usar el objeto global (y solo sí, la variable fue creado en el entorno global) para poder acceder a la variable de manera programática.
Código
window["Peliculas"+i]["titulo"]
Pero no hagas esto y mejor usa las estructuras apropiadas de tal manera que puedas hacer uso de todas las herramientas asociadas a esas estructuras y ni decir que ya no estás contaminando el entorno global.
Por otro lado, si no conoces el nombre de las claves: Por ejemplo, imagínate que dejas que el usuario añada sus claves valores. El usuario podría añadir a la Peliculas1 la clave "UltimaVezQueLaVi": "2018"; Entonces como trabajas tú con "UltimaVezQueLaVi" si tu no sabes de antemano que el usuario iba a añair exactamente esa propiedad?
Para este y otros casos. Te recomiendo usar Object.entries(elObjeto) para mostrar las propiedades y métodos enumerables de un objeto.
Qué es eso de enumerables o no enumerables? Los enumerables resumiendo muy muy mucho, son los que normalmente añades tú al objeto.
No se de donde salio esto, pero el usuario igual puede agregar propiedades no enumerables.
Hay propiedades y métodos no enumerables en tu objeto, pero entiendo que no te interesa mostrarlos ni saber que existen. Practicamente todo en javascript son objetos (Funciones también aunque no se use el constructor, ejem ejem). Por ejemplo cuando creas una función, en realidad estás creando un objeto que tiene métodos no enumerables como el método
Código
[[call]]
que sirve para poder llamar a la función. Todo esto funciona a nivel interno, asique no te interesa demasiado. Te lo comento para que sepas lo que es un método nó enumerable por si tienes curiosidad y para mayor entendimiento. Estos los puedes mostrar también (de varias formas), modificarlos para ser enumerbles o hacer tus propias propiedades no enumerables.
[[Call]] no es una propiedad, por lo tanto no tiene nada que ver con que sea enumerable o no. Mejor olvidarse de [[Call]] por ahora, porque no es algo que un principiante como el OP necesita saber.
No se, pero yo creo que el OP tenía una duda y ahora va a tener miles. No entiendo porque complicar un problema que es tan sencillo.
Lo único que hace esto es crear un arreglo con un string "Peliculas1". No hace referencia a la variable "Peliculas1". Tendrías que usar el objeto global (y solo sí, la variable fue creado en el entorno global) para poder acceder a la variable de manera programática.
Código
window["Peliculas"+i]["titulo"]
Pero no hagas esto y mejor usa las estructuras apropiadas de tal manera que puedas hacer uso de todas las herramientas asociadas a esas estructuras y ni decir que ya no estás contaminando el entorno global.
No se de donde salio esto, pero el usuario igual puede agregar propiedades no enumerables.
[[Call]] no es una propiedad, por lo tanto no tiene nada que ver con que sea enumerable o no. Mejor olvidarse de [[Call]] por ahora, porque no es algo que un principiante como el OP necesita saber.
No se, pero yo creo que el OP tenía una duda y ahora va a tener miles. No entiendo porque complicar un problema que es tan sencillo.
Exacto, estoy usando películas como propiedad de window y contaminando/polucionando el scope global. Tu dices que con mi respuesta la lio o le añado complejidad a algo sencillo, y tu te pones a hablar de scopes, closures y contaminación global, aclárate.
No quise entrar en más porque personalmente no suelo usar librerías externas y por lo tanto nunca tengo colisiones y por no alargar mi ya largo mensaje. Puede buscar sobre Immediately Invoked Function Expression (IIFE) para crear variables "locales".
Jajaja, pues si que me he liado ! Pero ya daré con la solución aunque me tenga que dar cabezazos contra la pantalla. Muchísimaas gracias a todos, sois unos máquinas !!!!
Exacto, estoy usando películas como propiedad de window y contaminando/polucionando el scope global.Tu dices que con mi respuesta la lio o le añado complejidad a algo sencillo, y tu te pones a hablar de scopes, closures y contaminación global, aclárate.
Yo no he hablado de closures para nada en este tema. El tema de scopes va completamente ligado a la pregunta porque es claramente acerca de variables. Encima, mi respuesta es a tu propuesta. Si te vengo a corregir la tengo que "liar".
A cerca de call No lo has leído todo porque dije que se pueden añadir propiedades no enumerables. Hacerlas enumerables no enumerables, etc.
Va, no lo vi la primera vez que leí el mensaje. El punto es que... enumerable o no, no tiene caso alguno. Nadie aquí pregunto por ese detalle. Y hay varias instancias que las consideraría normal en la que las propiedades no son enumerables.
He dicho que call es un método de una función. Qué es incorrecto?
[[Call]] no es ninguna propiedad de una función. Function.prototype.call si es una propiedad alcanzable en la cadena de herencia de funciones pero Function.prototype.call no es [[Call]].
The actual semantics of objects, in ECMAScript, are specified via algorithms called internal methods. Each object in an ECMAScript engine is associated with a set of internal methods that defines its runtime behaviour. These internal methods are not part of the ECMAScript language. They are defined by this specification purely for expository purposes.
"Estos métodos internos no forman parte del lenguaje de ECMAScript. Son definidos por está especificación para propósitos de exposición."