From 1109132f09d75da9a28b649c7677bb6ce07c40c0 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:41:45 -0500 Subject: initial commit --- .../adding_bouncing_balls_features/index.html | 205 +++++++++++ .../es/learn/javascript/objects/basics/index.html | 259 +++++++++++++ .../index.html" | 301 ++++++++++++++++ files/es/learn/javascript/objects/index.html | 67 ++++ .../javascript/objects/inheritance/index.html | 400 +++++++++++++++++++++ files/es/learn/javascript/objects/json/index.html | 339 +++++++++++++++++ .../objects/object-oriented_js/index.html | 307 ++++++++++++++++ .../objects/object_prototypes/index.html | 282 +++++++++++++++ 8 files changed, 2160 insertions(+) create mode 100644 files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html create mode 100644 files/es/learn/javascript/objects/basics/index.html create mode 100644 "files/es/learn/javascript/objects/ejercicio_pr\303\241ctico_de_construcci\303\263n_de_objetos/index.html" create mode 100644 files/es/learn/javascript/objects/index.html create mode 100644 files/es/learn/javascript/objects/inheritance/index.html create mode 100644 files/es/learn/javascript/objects/json/index.html create mode 100644 files/es/learn/javascript/objects/object-oriented_js/index.html create mode 100644 files/es/learn/javascript/objects/object_prototypes/index.html (limited to 'files/es/learn/javascript/objects') diff --git a/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html b/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html new file mode 100644 index 0000000000..c2aa7a9985 --- /dev/null +++ b/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html @@ -0,0 +1,205 @@ +--- +title: Añadiendo características a nuestra demo de bouncing balls +slug: Learn/JavaScript/Objects/Adding_bouncing_balls_features +tags: + - Aprender + - Evaluación + - JavaScript + - Objetos + - Orientado a objetos + - Principiante +translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}
+ +

En esta evaluación, se espera que use la demo de bouncing balls del artículo anterior como punto de partida y le agregue algunas características nuevas e interesantes.

+ + + + + + + + + + + + +
Prerrequisitos:Antes de intentar esta evaluación, debería haber revisado todos los artículos de este módulo.
Objetivo:Para probar la comprensión de objetos JavaScript y construcciones orientadas a objetos.
+ +

Punto de partida

+ +

Para iniciar esta evaluación, haz una copia local de  index-finished.html, style.css, y main-finished.js de nuestro último artículo en un nuevo directorio en tu ordenador.

+ +
+

Nota: Alternativamente, puede usar un sitio como JSBinThimble para hacer su evaluación. Puede pegar el HTML, CSS y JavaScript en uno de estos editores en línea. Si el editor en línea que está utilizando no tiene paneles JavaScript / CSS separados, sientase libre de poner en linea elementos <script>/<style> dentro de la página.

+
+ +

Resumen del proyecto

+ +

Nuestra demostración de la pelota hinchable es divertida, pero ahora queremos que sea un poco más interactiva agregando un círculo maligno controlado por el usuario, que se los comería si los atrapa. Tambien queremos testar nuestras destrezas como constructores de objetos creando un objeto Shape() genérico de que puedan heredar nuestra pelota y el círculo maligno. Finalmente, queremos añadir una puntuación para seguir el número de bolas que quedan por capturar.

+ +

La siguiente captura de pantalla te da una idea de cómo debería verse el programa final.

+ +

+ + + +

Para darle una idea eche un vistazo al ejemplo final (¡no mire el código fuente!)

+ +

Pasos para completar

+ +

Las siguientes secciones describen lo que debe hacer.

+ +

Creando nuestro nuevos objetos

+ +

Primero de todo, cambia la constructora existente de Ball() para que se convierta en un constructor Shape() y añade un nuevo constructor Ball():

+ +
    +
  1. El constructor Shape() debe definir las propiedades x, y, velX, y velY del mismo modo que lo hacía el constructor Ball() constructor original, pero no las propiedades color y size.
  2. +
  3. También debe definir una nueva propiedad exists, que se utiliza para realizar un seguimiento de si existen las bolas en el programa (no se han comido por el círculo maligno). Debe ser un boolean (true/false).
  4. +
  5. El constructor Ball() debe heredar las propiedades x, y, velX, velY, y exists del constructor Shape().
  6. +
  7. También debe definir propiedades color y size, como el constructor original Ball() hacía.
  8. +
  9. Recuerda configurar el prototype del constructor Ball() correctamente.
  10. +
+ +

Los métodos de la pelota draw(), update(), y collisionDetect() deben ser capaces de permanecer exactamente igual que antes.

+ +

También necesitas añadir un parámetro nuevo a la llamada del constructor new Ball() ( ... )  — El parámetro exists debe ser el quinto parámetro y debe tener un valor true.

+ +

En este punto, intente volver a cargar el código; debería funcionar igual que antes, con nuestros objetos rediseñados.

+ +

Definiendo EvilCircle()

+ +

Ahora es el momento de conocer al chico malo: ¡el EvilCircle()! Nuestro juego solo involucrará un círculo malvado, pero lo vamos a seguir definiendo usando un constructor que hereda de Shape() para que tengas algo de práctica. Es posible que desee agregar otro círculo a la aplicación más adelante que pueda ser controlado por otro jugador o tener varios círculos malvados controlados por computadora. Probablemente no vas a dominar el mundo con un solo círculo maligno, pero servirá para esta evaluación.

+ +

El constructor  EvilCircle() debe heredar x, y, velX, velY, y exists from Shape(), pero velX y velY debe ser igual a 20.

+ +

Debería hacer algo como Shape.call(this, x, y, 20, 20, exists);

+ +

Debe definir también sus propias propiedades, como las siguientes:

+ + + +

Otra vez, recuerda definir tus propiedades heredadas como parámetros en el constructor, y configura las propiedades prototype y constructor properties correc.tamente

+ +

Definiendo los métodos de EvilCircle()

+ +

EvilCircle() debe tener cuatro métodos como se desciben a continuación.

+ +

draw()

+ +

Este método tiene el mismo propósito que el método draw()de Ball(): Se encarga de dibujar la instancia del objeto en el lienzo. Funcionarán de una forma muy similar, así que puedes empezar copiando la definición de Ball.prototype.draw. Luego deberías hacer los siguientes cambios.:

+ + + +

checkBounds()

+ +

Este método hara lo mismo que la primera parte de la función update() de Ball() — mire para ver si el círculo maligno va a salir del borde de la pantalla y evite que lo haga. De nuevo, puede copiar la mayoría de la definición de Ball.prototype.update, hay algunos cambios que debe hacer:

+ + + +

setControls()

+ +

Este método agregará un detector de eventos onkeydown al objeto window para que cuando se presionen ciertas teclas del teclado, podamos mover el círculo maligno. El siguiente bloque de código debe colocarse dentro de la definición del método:

+ +
var _this = this;
+window.onkeydown = function(e) {
+    if (e.keyCode === 65) {
+      _this.x -= _this.velX;
+    } else if (e.keyCode === 68) {
+      _this.x += _this.velX;
+    } else if (e.keyCode === 87) {
+      _this.y -= _this.velY;
+    } else if (e.keyCode === 83) {
+      _this.y += _this.velY;
+    }
+  }
+ +

Por tanto cuando se presiona una tecla, el evento del objeto keyCode se consulta para averiguar que tecla se ha presionado. Si es uno de los cuatro representados por los códigos clave especificados, entonces el círculo maligno se moverá a la izquierda / derecha / arriba / abajo.

+ + + +

collisionDetect()

+ +

Este método actuará de una forma muy similar al método collisionDetect() de Ball(), así que puede usar una copia de eso como una base para el nuevo método. Pero hay algunas diferencias:

+ + + +

Trayendo el círculo del mal al programa.

+ +

Ahora que hemos definido el círculo maligno, debemos hacerlo aparecer en nuestra escena. Para hacerlo, necesitas hacer alguno cambios a la función loop().

+ + + +

Implementando el contador de puntuación.

+ +

Para implementar el contador de puntuación sigue estos pasos:

+ +
    +
  1. En tu archivo HTML añade un elemento {{HTMLElement("p")}} justo debajo del elemento {{HTMLElement("h1")}} que contiene el texto "Ball count: ".
  2. +
  3. En tu archivo CSS, agregue la siguiente regla en la parte inferior: +
    p {
    +  position: absolute;
    +  margin: 0;
    +  top: 35px;
    +  right: 5px;
    +  color: #aaa;
    +}
    +
  4. +
  5. En su JavaScript, realice las siguientes actualizaciones: +
      +
    • Cree una variable que almacene una referencia al párrafo.
    • +
    • Mantenga un recuento de la cantidad de bolas en la pantalla de alguna manera.
    • +
    • Incrementa el conteo y muestra el número actualizado de bolas cada vez que se agrega una bola a la escena.
    • +
    • Disminuye el conteo y muestra el número actualizado de bolas cada vez que el círculo maligno se come una bola (hace que no exista).
    • +
    +
  6. +
+ +

Consejos

+ + + +

Evaluación

+ +

Si está siguiendo esta evaluación como parte de un curso organizado, debe poder entregar su trabajo a su maestro / mentor para que lo marque. Si está aprendiendo solo, puede obtener la guía de calificación con bastante facilidad preguntando en el discussion thread for this exercise, o en el #mdn IRC channel en Mozilla IRC. Prueba a hacer el ejercicio primero — no hay nada que ganar con trampa!

+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}

+ +

En este módulo

+ + diff --git a/files/es/learn/javascript/objects/basics/index.html b/files/es/learn/javascript/objects/basics/index.html new file mode 100644 index 0000000000..a04cdb6a81 --- /dev/null +++ b/files/es/learn/javascript/objects/basics/index.html @@ -0,0 +1,259 @@ +--- +title: Conceptos básicos de los objetos JavaScript +slug: Learn/JavaScript/Objects/Basics +tags: + - API + - Aprender + - Artículo + - JavaScript + - Novato + - Object + - Objeto + - Principiante + - Sintaxis + - instancia + - 'l10n:priority' + - notación de corchetes + - notación de punto + - objeto literal + - tehoría + - this +translation_of: Learn/JavaScript/Objects/Basics +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}
+ +

En éste artículo, veremos fundamentos de sintaxis de los objetos de JavaScript y revisaremos algunas características de JavaScript que ya hemos analizado anteriormente en el curso, reiterando el hecho de que muchas de las funciones con las que ya has tratado de hecho son objetos.

+ + + + + + + + + + + + +
Prerrequisitos:Conocimientos básicos de informática, conocimientos básicos de HTML y CSS, familiaridad con los principios básicos de JavaScript (consulta Primeros pasos y Bloques de construcción).
Objetivo:Para comprender la teoría básica detrás de la programación orientada a objetos, cómo esto se relaciona con JavaScript ("la mayoría de las cosas son objetos") y cómo empezar a trabajar con objetos de JavaScript.
+ +

Conceptos básicos de objeto

+ +

Un objeto es una colección de datos relacionados y/o funcionalidad (que generalmente consta de algunas variables y funciones, que se denominan propiedades y métodos cuando están dentro de objetos). Vamos a trabajar a través de un ejemplo para mostrate cómo son.

+ +

Para empezar, haz una copia local de nuestro archivo oojs.html . Esto contiene muy poco: un elemento {{HTMLElement ("script")}} para que escribas tu código fuente en él. Lo usaremos como base para explorar la sintaxis básica de los objetos.

+ +

Al igual que con muchas cosas en JavaScript, la creación de un objeto a menudo comienza con la definición e iniciación de una variable. Intenta ingresar lo siguiente debajo del código JavaScript que ya está en tu archivo, luego guarda y actualiza:

+ +
var persona = {};
+ +

Si ingresas persona en tu entrada de texto y presionas el botón, debes obtener el siguiente resultado:

+ +
[objeto Objeto]
+ +

¡Felicidades!, acabas de crear tu primer objeto. ¡Trabajo realizado! Pero este es un objeto vacío, por lo que realmente no podemos hacer mucho con él. Actualicemos nuestro objeto para que se vea así:

+ +
var persona = {
+  nombre: ['Bob', 'Smith'],
+  edad: 32,
+  genero: 'masculino',
+  intereses: ['música', 'esquí'],
+  bio: function () {
+    alert(this.nombre[0] + '' + this.nombre[1] + ' tiene ' + this.edad + ' años. Le gusta ' + this.intereses[0] + ' y ' + this.intereses[1] + '.');
+  },
+  saludo: function() {
+    alert('Hola, Soy '+ this.nombre[0] + '. ');
+  }
+};
+
+ +

Después de guardar y actualizar, intenta ingresar algunos de los siguientes en tu entrada de texto:

+ +
persona.nombre
+persona.nombre[0]
+persona.edad
+persona.intereses[1]
+persona.bio()
+persona.saludo()
+ +

¡Ahora tienes algunos datos y funcionalidades dentro de tu objeto, y ahora puedes acceder a ellos con una sintaxis simple y agradable!

+ +
+

Nota: Si tienes problemas para hacer que esto funcione, intenta comparar tu código con nuestra versión - ve oojs-finished.html (también ve que se ejecuta en vivo). La versión en vivo te dará una pantalla en blanco, pero eso está bien. De nuevo, abre tu devtools e intenta escribir los comandos anteriores para ver la estructura del objeto.

+
+ +

Entonces, ¿qué está pasando aquí? Bien, un objeto se compone de varios miembros, cada uno de los cuales tiene un nombre (por ejemplo, nombre y edad) y un valor (por ejemplo, ['Bob', 'Smith'] y 32). Cada par nombre/valor debe estar separado por una coma, y el nombre y el valor en cada caso están separados por dos puntos. La sintaxis siempre sigue este patrón:

+ +
var nombreObjeto = {
+  miembro1Nombre: miembro1Valor,
+  miembro2Nombre: miembro2Valor,
+  miembro3Nombre: miembro3Valor
+}
+ +

El valor de un miembro de un objeto puede ser prácticamente cualquier cosa: en nuestro objeto persona tenemos una cadena de texto, un número, dos arreglos y dos funciones. Los primeros cuatro elementos son elementos de datos y se denominan propiedades del objeto. Los dos últimos elementos son funciones que le permiten al objeto hacer algo con esos datos, y se les denomina métodos del objeto.

+ +

Un objeto como este se conoce como un objeto literal — literalmente hemos escrito el contenido del objeto tal como lo fuimos creando. Esto está en contraste con los objetos instanciados de las clases, que veremos más adelante.

+ +

Es muy común crear un objeto utilizando un objeto literal cuando deseas transferir una serie de elementos de datos relacionados y estructurados de alguna manera, por ejemplo, enviando una solicitud al servidor para ponerla en una base de datos. Enviar un solo objeto es mucho más eficiente que enviar varios elementos individualmente, y es más fácil de procesar que con un arreglo, cuando deseas identificar elementos individuales por nombre.

+ +

Notación de punto

+ +

Arriba, accediste a las propiedades y métodos del objeto usando notación de punto (dot notation). El nombre del objeto (persona) actúa como el espacio de nombre (namespace); al cual se debe ingresar primero para acceder a cualquier elemento encapsulado dentro del objeto. A continuación, escribe un punto y luego el elemento al que deseas acceder: puede ser el nombre de una simple propiedad, un elemento de una propiedad de arreglo o una llamada a uno de los métodos del objeto, por ejemplo:

+ +
persona.edad
+persona.intereses[1]
+persona.bio()
+ +

Espacios de nombres secundarios

+ +

Incluso es posible hacer que el valor de un miembro del objeto sea otro objeto. Por ejemplo, intenta cambiar el miembro nombre de

+ +
nombre: ['Bob', 'Smith'],
+ +

a

+ +
nombre : {
+  pila: 'Bob',
+  apellido: 'Smith'
+},
+ +

Aquí estamos creando efectivamente un espacio de nombre secundario (sub-namespace). Esto suena complejo, pero en realidad no es así: para acceder a estos elementos solo necesitas un paso adicional que es encadenar con otro punto al final. Prueba estos:

+ +
persona.nombre.pila
+persona.nombre.apellido
+ +

Importante: en este punto, también deberás revisar tu código y cambiar cualquier instancia de

+ +
nombre[0]
+nombre[1]
+ +

a

+ +
nombre.pila
+nombre.apellido
+ +

De lo contrario, sus métodos ya no funcionarán.

+ +

Notación de corchetes

+ +

Hay otra manera de acceder a las propiedades del objeto, usando la notación de corchetes. En lugar de usar estos:

+ +
persona.edad
+persona.nombre.pila
+ +

Puedes usar

+ +
persona['edad']
+persona['nombre']['pila']
+ +

Esto se ve muy similar a cómo se accede a los elementos en un arreglo, y básicamente es lo mismo: en lugar de usar un número de índice para seleccionar un elemento, se esta utilizando el nombre asociado con el valor de cada miembro. No es de extrañar que los objetos a veces se denominen arreglos asociativos: asocian cadenas de texto a valores de la misma manera que las arreglos asocian números a valores.

+ +

Establecer miembros de objetos

+ +

Hasta ahora solo hemos buscado recuperar (u obtener) miembros del objeto: también puede establecer (actualizar) el valor de los miembros del objeto simplemente declarando el miembro que deseas establecer (usando la notación de puntos o corchetes), de esta manera:

+ +
persona.edad = 45;
+persona['nombre']['apellido'] = 'Cratchit';
+ +

Intenta ingresar estas líneas y luego vuelve a ver a los miembros para ver cómo han cambiado:

+ +
persona.edad
+persona['nombre']['apellido']
+ +

Establecer miembros no solo es actualizar los valores de las propiedades y métodos existentes; también puedes crear miembros completamente nuevos. Prueba estos:

+ +
persona['ojos'] = 'avellana';
+persona.despedida = function() { alert("¡Adiós a todos!"); }
+ +

Ahora puedes probar a los nuevos miembros:

+ +
persona['ojos']
+person.despedida()
+ +

Un aspecto útil de la notación de corchetes es que se puede usar para establecer dinámicamente no solo los valores de los miembros, sino también los nombres de los miembros. Digamos que queremos que los usuarios puedan almacenar tipos de valores personalizados en sus datos personales, escribiendo el nombre y el valor del miembro en dos entradas de texto. Podríamos obtener esos valores de esta manera:

+ +
var nombrePerzonalizado = entradaNombre.value;
+var valorPerzonalizado = entradaValor.value;
+ +

entonces podríamos agregar este nuevo miembro nombre y valor al objeto persona de esta manera:

+ +
persona[nombrePerzonalizado] = valorPerzonalizado;
+ +

Para probar esto, intenta agregar las siguientes líneas en tu código, justo debajo de la llave de cierre del objeto persona:

+ +
var nombrePerzonalizado = 'altura';
+var valorPerzonalizado = '1.75m';
+persona[nombrePerzonalizado] = valorPerzonalizado;
+ +

Ahora intenta guardar y actualizar, e ingresa lo siguiente en tu entrada de texto:

+ +
persona.altura
+ +

Agregar una propiedad a un objeto no es posible con la notación de puntos, que solo puede aceptar un nombre de miembro literal, no un valor variable que apunte a un nombre.

+ +

¿Qué es "this" (este)?

+ +

Es posible que hayas notado algo un poco extraño en nuestros métodos. Mira esto, por ejemplo:

+ +
saludo: function() {
+  alert('¡Hola!, Soy '+ this.nombre.pila + '.');
+}
+ +

Probablemente te estés preguntando qué es "this". La palabra clave this se refiere al objeto actual en el que se está escribiendo el código, por lo que en este caso this es equivalente a la persona. Entonces, ¿por qué no escribir persona en su lugar? Como verás en el artículo JavaScript orientado a objetos para principiantes cuando comenzaremos a crear constructores, etc., this es muy útil: siempre asegurará que se usen los valores correctos cuando cambie el contexto de un miembro (por ejemplo, dos diferentes instancias de objetos persona) pueden tener diferentes nombres, pero querráx usar su propio nombre al decir su saludo).

+ +

Vamos a ilustrar lo que queremos decir con un par de objetos persona simplificados:

+ +
var persona1 = {
+  nombre: 'Chris',
+  saludo: function() {
+    alert('¡Hola!, Soy '+ this.nombre + '.');
+  }
+}
+
+var persona2 = {
+  nombre: 'Brian',
+  saludo: function() {
+    alert('¡Hola!, Soy '+ this.nombre + '.');
+  }
+}
+ +

En este caso, persona1.saludo() mostrará "¡Hola!, Soy Chris"; persona2.saludo() por otro lado mostrará "¡Hola!, Soy Brian", aunque el código del método es exactamente el mismo en cada caso. Como dijimos antes, this es igual al objeto en el que está el código; esto no es muy útil cuando se escriben objetos literales a mano, pero realmente se vuelve útil cuando se generan objetos dinámicamente (por ejemplo, usando constructores) Todo se aclarará más adelante.

+ +

Has estado usando objetos todo el tiempo

+ +

A medida que has estado repasando estos ejemplos, probablemente hayas pensando que la notación de puntos que has usando es muy familiar. ¡Eso es porque la has estado usando a lo largo del curso! Cada vez que hemos estado trabajando en un ejemplo que utiliza una API de navegador incorporada o un objeto JavaScript, hemos estado usando objetos, porque tales características se crean usando exactamente el mismo tipo de estructuras de objetos que hemos estado viendo aquí, aunque más complejos que nuestros propios ejemplos personalizados.

+ +

Entonces cuando usaste métodos de cadenas de texto como:

+ +
myCadena.split(',');
+ +

Estabas usando un método disponible en una instancia de la clase String. Cada vez que creas una cadena en tu código, esa cadena se crea automáticamente como una instancia de String, y por lo tanto tiene varios métodos/propiedades comunes disponibles en ella.

+ +

Cuando accediste al modelo de objetos del documento (document object model) usando líneas como esta:

+ +
var miDiv = document.createElement('div');
+var miVideo = document.querySelector('video');
+ +

Estaba usando métodos disponibles en una instancia de la clase Document. Para cada página web cargada, se crea una instancia de Document, llamada document, que representa la estructura, el contenido y otras características de la página entera, como su URL. De nuevo, esto significa que tiene varios métodos/propiedades comunes disponibles en él.

+ +

Lo mismo puede decirse de prácticamente cualquier otro Objeto/API incorporado que hayad estado utilizando: Array, Math, etc.

+ +

Ten en cuenta que los Objetos/API incorporados no siempre crean instancias de objetos automáticamente. Como ejemplo, la API de Notificaciones, que permite que los navegadores modernos activen las notificaciones del sistema, requiere que crees una instancia de un nuevo objeto para cada notificación que desees disparar. Intenta ingresar lo siguiente en tu consola de JavaScript:

+ +
var miNotificacion = new Notification('¡Hola!');
+ +

De nuevo, veremos qué son los constructores en un artículo posterior.

+ +
+

Nota: Es útil pensar en la forma en que los objetos se comunican como paso de mensajes — cuando un objeto necesita otro objeto para realizar algún tipo de acción a menudo enviará un mensaje a otro objeto a través de uno de sus métodos, y esperará una respuesta, que conocemos como un valor de retorno.

+
+ +

Resumen

+ +

Enhorabuena, has llegado al final de nuestro primer artículo sobre objetos JS: ahora debes tener una buena idea de cómo trabajar con objetos en JavaScript, incluida la creación de tus propios objetos simples. También debes apreciar que los objetos son muy útiles como estructuras para almacenar datos y funcionalidades relacionadas; si trataras de hacer un seguimiento de todas las propiedades y métodos en nuestro objeto persona como variables y funciones separadas, sería ineficiente y frustrante, y tendríamos el riesgo de chocar con otras variables y funciones que tienen los mismos nombres. Los objetos nos permiten mantener la información segura y protegida en su propio paquete, fuera del peligro.

+ +

En el próximo artículo comenzaremos a ver la teoría de programación orientada a objetos (OOP) y cómo se pueden usar dichas técnicas en JavaScript.

+ +

{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}

diff --git "a/files/es/learn/javascript/objects/ejercicio_pr\303\241ctico_de_construcci\303\263n_de_objetos/index.html" "b/files/es/learn/javascript/objects/ejercicio_pr\303\241ctico_de_construcci\303\263n_de_objetos/index.html" new file mode 100644 index 0000000000..6dfaaf0d08 --- /dev/null +++ "b/files/es/learn/javascript/objects/ejercicio_pr\303\241ctico_de_construcci\303\263n_de_objetos/index.html" @@ -0,0 +1,301 @@ +--- +title: Ejercicio práctico de construcción de objetos +slug: Learn/JavaScript/Objects/Ejercicio_práctico_de_construcción_de_objetos +translation_of: Learn/JavaScript/Objects/Object_building_practice +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}
+ +

En los artículos anteriores se explicó lo fundamental de la teoría de los objetos en JavaScript asi como su sintaxis, para que Usted tenga un punto de partida sólido. En éste artículo, desarrollaremos un ejercicio práctico para ganar experiencia en la programación de objetos en JavaScript, con un resultado divertido y colorido.

+ + + + + + + + + + + + +
Pre-requisitos:Conocimientos básicos de computadores. Entendimiento básico de HTML y CSS. Familiaridad con los conceptos básicos de JavaScript (vea Primeros Pasos con JavaScript y Elementos básicos de JavaScript)  y OOJS (vea Conceptos básicos de los objetos JavaScript).
Objetivos:Ganar experiencia en el uso de objetos y el uso de programación orientada a objetos en un contexto realista.
+ +

Lanzemos algunas pelotas

+ +

Es éste artículo escribiremos un programa demo del juego clásico de pelotas que rebotan para mostrar la gran útilidad de los objetos en JavaScript. En éste demo las pelotas rebotaran en la pantalla y cambiaran de color cuando choquen unas con otras. Así, al final del ejemplo tendremos algo como esto:

+ +

+ +
    +
+ +

En este ejemplo se utilizará Canvas API para dibujar las pelotas en la pantalla y la API requestAnimationFrame para animar todo el contenido de la pantalla. No es necesario que conozca estas funciones previamente. Esperamos que al final de este artículo, quizás pueda estar interesado en explorar su uso y capacidades más en detalle. Durante este desarrollo usaremos objetos y algunas técnicas para hacer que las pelotas puedan rebotar en los bordes y comprobar cuando choquen entre ellas (ésto se conoce como detección de colisiones). 

+ +

Primeros pasos

+ +

Para comenzar haga una copia en su computador de los archivos:  index.html, style.css, y main.js. Estos contienen:

+ +
    +
  1. Un documento HTML sencillo con un elemento <h1>, un elemento <canvas> en el que podamos dibujar los gráficos y otros elementos para aplicar los estilos CSS y el código JavaScript. 
  2. +
  3. Algunos estilos sencillos que servirán para ubicar el elemento <h1>, ocultar la barra de desplazamiento y los margenes del borde de la página (para que luzca mejor).
  4. +
  5. Un archivo JavaScript que sirve para definir el elemento <canvas> y las funciones que vamos a usar.
  6. +
+ +

La primera parte del script es:

+ +
var canvas = document.querySelector('canvas');
+
+var ctx = canvas.getContext('2d');
+
+var width = canvas.width = window.innerWidth;
+var height = canvas.height = window.innerHeight;
+ +

Este script obtiene una referencia del elemento <canvas>, luego llama al método getContext() para definir un contexto en el cual se pueda comenzar a dibujar. La resultado de la variable  (ctx) es el objeto que representa directamente el área de dibujo del <canvas> y permite dibujar elementos 2D en él. 

+ +

A continuación se da valor a las variables width and height que corresponden al ancho y alto del elemento canvas (representado por las propiedades canvas.width y canvas.height), de manera que el alto y ancho coincidan con el alto y ancho del navegador (viewport)  cuyos valores se obtienen directamente de las propiedades window.innerWidth window.innerHeight.

+ +

Puede ver que en el código se encadenan varias asignaciones, para obtener valores más rápidamente. Esto se puede hacer.

+ +

La última parte del script, es la siguiente:

+ +
function random(min, max) {
+  var num = Math.floor(Math.random() * (max - min + 1)) + min;
+  return num;
+}
+ +

Esta función recibe dos números como argumentos de entrada (valor mínimo y maximo) y devuelve un número aleatorio entre ellos.

+ +

Modelando una pelota en nuestro programa

+ +

Nuestro programa tendrá montones de pelotas rebotando por toda la pantalla. Ya que todas las pelotas tendrán el mismo comportamiento, tiene sentido representarlas con un objeto. Empezamos definiendo un constructor para el objeto pelota (Ball), en nuestro código.

+ +
function Ball(x, y, velX, velY, color, size) {
+  this.x = x; //posición horizontal
+  this.y = y; //posición vertical
+  this.velX = velX; //velocidad horizontal
+  this.velY = velY; //velocidad vertical
+  this.color = color; //color
+  this.size = size; //tamaño
+}
+ +

Aquí incluimos algunos parámetros que serán las propiedades que cada pelota necesita para funcionar en nuestro programa: 

+ + + +

Con esto se resuelven las propiedades del objeto, ¿Pero qué hacemos con los métodos? Ya que queremos que las pelotas realicen algo en nuestro programa. 

+ +

Dibujando las pelotas

+ +

Para dibujar, añadiremos el siguiente método draw() al prototipo del objeto Ball():

+ +
Ball.prototype.draw = function() {
+  ctx.beginPath();
+  ctx.fillStyle = this.color;
+  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
+  ctx.fill();
+}
+ +

Con esta función cada objeto pelota Ball() puede dibujarse en la pantalla utilizando el contexto 2D definido anteriormente (ctx)  

+ + + +

Ya se puede empezar a testear el objeto.

+ +
    +
  1. Guarde el código hasta ahora, y cargue el archivo HTML en un navegador.
  2. +
  3. Abra la consola de JavaScript en el navegador, y refresque la página, para que el tamaño del canvas modifique sus dimensiones adaptándose al viewport con la consola abierta. 
  4. +
  5. Teclee lo siguiente en la consola para crear una nueva pelota. +
    var testBall = new Ball(50, 100, 4, 4, 'blue', 10);
    +
  6. +
  7. Pruebe a llamar a las variables miembro: +
    testBall.x
    +testBall.size
    +testBall.color
    +testBall.draw()
    +
  8. +
  9. Al teclear la última línea, debería ver que la pelota se dibuja en alguna parte del canvas
  10. +
+ +

Actualizando los datos de la pelota

+ +

Ahora podemos dibujar una pelota en una posición dada, pero para empezar a moverla, se necesita una función de actualización de algún tipo. Podemos añadir el código a continuación, al final del archivo de JavaScript, para añidir un método de actualización update() en el prototipo de la clase Ball()

+ +
Ball.prototype.update = function() {
+  if ((this.x + this.size) >= width) {
+    this.velX = -(this.velX);
+  }
+
+  if ((this.x - this.size) <= 0) {
+    this.velX = -(this.velX);
+  }
+
+  if ((this.y + this.size) >= height) {
+    this.velY = -(this.velY);
+  }
+
+  if ((this.y - this.size) <= 0) {
+    this.velY = -(this.velY);
+  }
+
+  this.x += this.velX;
+  this.y += this.velY;
+}
+ +

Las cuatro primeras partes de la función verifican si la pelota a alcanzado el borde del canvas. Si es así, se invierte la dirección de la velocidad, para que la pelota se mueva en la dirección contraria. Así, si la pelota va hacia arriba, (velY positiva) , entonces la velocidad vertical es cambiada, para que se mueva hacia abajo (velY negativa).

+ +

Los cuatro posibles casos son: 

+ + + +

En cada caso, se ha tenido en cuenta el tamaño (size) de la pelota en los cálculos, ya que las coordenadas x e y corresponden al centro de la pelota, pero lo que queremos ver es el borde de la pelota cuando choca con el perímetro del canvas — que la pelota rebote, cuando está a medio camino fuera de el —.

+ +

Las dos últimas líneas de código, suman  la velocidad en x (velX) al valor de la coordenada x  , y el valor de la velocidad en y (velY)  a la coordenada y —  con esto se consigue el efecto de que la pelota se mueva cada vez que este método es llamado. 

+ +

Llegados a este punto: ¡continuemos, con las animaciones!

+ +

Animando las pelotas

+ +

Hagamos esto divertido! Ahora vamos a empezar a añadir pelotas al canvas, y animándolas.

+ +

1. Primero, necesitamos algún sitio donde guardas las pelotas. El siguiente arreglo hará esta función — añádela al final de tu código. 

+ +
var balls = [];
+ +

Todos los programas que generan animaciones normalmente tienen un bucle de animación, que sirve para actualizar los datos del programa, para entonces generar la imagen correspondiente; esta es la estrategia básica para la mayor parte de juegos y programas similares. 

+ +

2. Añadamos las siguientes instrucciones al final del código: 

+ +
function loop() {
+  ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
+  ctx.fillRect(0, 0, width, height);
+
+  while (balls.length < 25) {
+    var size = random(10,20);
+    var ball = new Ball(
+      // la posición de las pelotas, se dibujará al menos siempre
+      // como mínimo a un ancho de la pelota de distancia al borde del
+      // canvas, para evitar errores en el dibujo
+      random(0 + size,width - size),
+      random(0 + size,height - size),
+      random(-7,7),
+      random(-7,7),
+      'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')',
+      size
+    );
+    balls.push(ball);
+  }
+
+  for (var i = 0; i < balls.length; i++) {
+    balls[i].draw();
+    balls[i].update();
+  }
+
+  requestAnimationFrame(loop);
+}
+ +

Nuestra función de bucle: loop(), hace lo siguiente: 

+ + + +

3. Por último, pero no menos importante, añadimos la siguiente línea, al final del código.-- es necesario llamar a la función inicialmente para que la animación comience. 

+ +
loop();
+ +

Eso es todo para la parte básica — pruebe a guardar el código y refrescar el navegador para comprobar si aparecen las pelotas rebotando!

+ +

Añadiendo la detección de colisiones

+ +

Ahora, un poco de diversión, añadamos la detección de colisiones a nuestro código. Así las pelotas, sabrán cuando chocan unas contra otras.

+ +
    +
  1. El primer paso, será añadir el código a continuación a continuación de donde se definió el método  update(). (en código de Ball.prototype.update) + +
    Ball.prototype.collisionDetect = function() {
    +  for (var j = 0; j < balls.length; j++) {
    +    if (!(this === balls[j])) {
    +      var dx = this.x - balls[j].x;
    +      var dy = this.y - balls[j].y;
    +      var distance = Math.sqrt(dx * dx + dy * dy);
    +
    +      if (distance < this.size + balls[j].size) {
    +        balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')';
    +      }
    +    }
    +  }
    +}
    + +

    Esta función es un poco complicada, así que no hay que preocuparse mucho si de momento no se comprende del todo.  

    + +
      +
    • Para cada pelota, necesitamos comprobar si chocará con cada una de las otras pelotas. Para esto, en un bucle for para recorrer todas las pelotas.
    • +
    • Dentro del bucle, usamos un if  para comprobar si la pelota que estamos mirando en ese ciclo del bucle for es la pelota que estamos mirando. No queremos mirar si una pelota ha chocado consigo misma. Para esto miramos si la pelota actual (es decir la pelota que está invocando al método que resuelve la detección de colisiones) es la misma que la indicada por el bucle. Usamos un operador ! para indicar una negación en la comparación, así que el código dentro de la condición  solo se ejecuta si estamos mirando dos pelotas distintas.
    • +
    • Usamos un algoritmo común para comprobar la colisión de los dos pelotas. Básicamente miramos si el área de dos círculos se superponen.  Esto se explica mejor en el enlace detección de colision 2D.
    • +
    • En este caso, únicamente se define la propiedad de color para las dos pelotas, cambiándolas a un nuevo color aleatorio. Se podría haber hecho cosas más complicadas, como que las pelotas rebotasen una con la otra de forma realista, pero esto habría supuesto un desarrollo más complejo. Para desarrollar esos efectos de simulación física, los desarrolladores tienden a usar librerías de física como PhysicsJS, matter.js, Phaser, etc.
    • +
    +
  2. +
  3. También es necesario llamar este método en cada instante de la animación. balls[i].update(); en la línea: +
    balls[i].collisionDetect();
    +
  4. +
  5. Guardar y refrescar la demo de nuevo y podrá ver como las pelotas cambian de color cuando chocan entre ellas.
  6. +
+ +
+

Nota: Si tiene problemas para hacer funcionar este ejemplo, puede comparar su código JavaScript, con el código de la version_final (y también ver como funciona al ejecutarla).

+
+ +

Resumen

+ +

Esperamos que se haya divertido escribiendo su propio mundo de pelotas que chocan aleatoriamente, usando objetos y programación orientada a objetos. Esto debería haberle dado una práctica útil y haber sido un buen ejemplo. 

+ +

Lea también

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}

+ +

En este módulo

+ + diff --git a/files/es/learn/javascript/objects/index.html b/files/es/learn/javascript/objects/index.html new file mode 100644 index 0000000000..191d23bc9f --- /dev/null +++ b/files/es/learn/javascript/objects/index.html @@ -0,0 +1,67 @@ +--- +title: Introducción a los objetos JavaScript +slug: Learn/JavaScript/Objects +tags: + - Aprender + - Artículo + - Assessment + - CodingScripting + - Evaluación + - Guía + - JavaScript + - Objetos + - Principiante + - TopicStub + - Tutorial +translation_of: Learn/JavaScript/Objects +--- +
{{LearnSidebar}}
+ +

En JavaScript, la mayoría de las cosas son objetos, desde características del núcleo de JavaScript como arrays hasta el explorador {{Glossary("API", "APIs")}} construído sobre JavaScript. Incluso puedes crear tus propios objetos para encapsular funciones y variables relacionadas dentro de paquetes eficientes que actúan como prácticos contenedores de datos. La naturaleza de JavaScript basada-en-objetos es importante de entender, si quieres avanzar con tu conocimiento del lenguaje, y por ello hemos hecho este módulo para ayudarte. Aquí enseñamos teoría de objetos y sintaxis en detalle, y luego veremos como crear tus propios objetos.

+ +

¿Buscas convertirte en desarrollador web de front-end?

+ +

Hemos puesto un curso que incluye toda la información esencial que necesitas para alcanzar esa meta

+ +

Comienza aquí

+ +

Prerrequisitos

+ +

Antes de empezar este módulo deberías estar familiarizado con  {{Glossary("HTML")}} and {{Glossary("CSS")}}. Te aconsejamos trabajar los módulos Introducción a HTML y Introducción a CSS antes de empezar con JavaScript.

+ +

También deberías conocer lo básico de Javascript antes de entrar en detalle en los objetos de Javascript. Antes de empezar este módulo, revisa Primeros pasos con JavaScript y Elementos básicos de Java​Script.

+ +
+

Nota: Si trabajas en un ordenador, tablet u otro dispositivo donde no puedas editar tus propios ficheros, prueba a ejecutar los ejemplos de código online en páginas como JSBin o Thimble.

+
+ +

Guías

+ +
+
Principios básicos de los Objetos
+
En este primer artículo sobre los objetos en Javascript, aprenderemos los fundamentos de la sintaxis de objetos en Javascript y revisaremos algunas características ya vistas anteriormente en el curso, remarcando el hecho que muchas de ellas son en realidad objetos.
+
JavaScript Orientado a Objetos para principiantes
+
Una vez vistos los principios básicos, nos centraremos en JavaScript orientado a objetos (OOJS) — este artículo presenta los elementos básicos de la teoría de programación orientada a objetos (OOP), posteriormente explora la manera en que JavaScript emula las clases de un objeto a través de los constructores de funciones, y cómo crea las instancias de un objeto.
+
Prototipos de Objetos
+
Los prototipos son el mecanismo por el cual los objetos en JavaScript heredan caraterísticas entre sí, y funcionan de manera distinta a los mecanismos de herencia  de los lenguages de programación orientada a objetos clásicos.
+
Herencia en JavaScript
+
Con la mayoría de los detalles sangrientos de OOJS ahora explicados, este artículo muestra cómo crear clases de objetos "hijo" (constructores) que heredan características de sus clases "principales". Además, presentamos algunos consejos sobre cuándo y dónde puede usar OOJS.
+
Trabajando con datos JSON
+
La notación de objetos JavaScript (JSON) es un formato estándar basado en texto para representar datos estructurados basados en la sintaxis de objetos de JavaScript, que se usa comúnmente para representar y transmitir datos en sitios web (es decir, enviar datos desde el servidor al cliente; se mostrará en una página web). Lo encontrarás con bastante frecuencia, por lo que en este artículo te proporcionamos todo lo que necesitas para trabajar con JSON mediante JavaScript, incluido el análisis del JSON para que puedas acceder a los elementos de datos y escribir su propio JSON.
+
Práctica de Construcción de Objetos
+
En artículos anteriores vimos toda la teoría esencial de los objetos de JavaScript y los detalles de sintaxis, brindándote una base sólida para comenzar. En este artículo nos sumergimos en un ejercicio práctico, que te dará más práctica en la construcción de objetos personalizados de JavaScript, que producen algo divertido y colorido: algunas pelotas de colores rebotando.
+
+ +

Evaluaciones

+ +
+
Agregar funciones a nuestra demo de "Pelotas Rebotando"
+
En esta evaluación, se espera que utilices la demostración de pelotas que rebotan del artículo anterior como punto de partida y que le agregues algunas características nuevas e interesantes.
+
+ +

Vea también

+ +
+
Aprender JavaScript
+
Un excelente recurso para los aspirantes a desarrolladores web —prenda JavaScript en un entorno interactivo, con lecciones cortas y pruebas interactivas, guiado por una evaluación automatizada. Las primeras 40 lecciones son gratuitas, y el curso completo está disponible por un pequeño pago único.
+
diff --git a/files/es/learn/javascript/objects/inheritance/index.html b/files/es/learn/javascript/objects/inheritance/index.html new file mode 100644 index 0000000000..e1cbba42da --- /dev/null +++ b/files/es/learn/javascript/objects/inheritance/index.html @@ -0,0 +1,400 @@ +--- +title: Herencia en JavaScript +slug: Learn/JavaScript/Objects/Inheritance +translation_of: Learn/JavaScript/Objects/Inheritance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}
+ +

Con la mayoría de los detalles internos de OOJS (JavaScript Orientado a Objetos) explicados, este artículo muestra cómo crear clases "hijo" (constructores) que heredan características de sus clases "padre". Además, presentamos algunos consejos sobre cuándo y dónde puedes usar OOJS y cómo se crean las clases con la sintaxis moderna de ECMAScript.

+ + + + + + + + + + + + +
Pre-requisitos:Conocimientos básicos de informática, una comprensión básica de HTML y CSS, familiaridad con los principios básicos de JavaScript (ver Primeros pasos y Construyendo bloques) y conceptos básicos de OOJS (ver Introduccion a objetos).
Objetivo:Entender cómo es posible implementar la herencia en JavaScript.
+ +

Herencia prototípica

+ +

Hasta ahora hemos visto algo de herencia en acción — hemos visto cómo funcionan las cadenas de prototipos, y cómo los miembros son heredados subiendo una cadena. Pero principalmente esto ha involucrado funciones integradas del navegador. ¿Cómo creamos un objeto en JavaScript que hereda de otro objeto?

+ +

Exploremos cómo hacer esto con un ejemplo concreto.

+ +

Primeros pasos

+ +

Primero que nada, hazte una copia local de nuestro archivo  oojs-class-inheritance-start.html (míralo corriendo en vivo también). Dentro de aquí encontrarás el mismo ejemplo de constructor de Persona() que hemos estado usando a través del módulo, con una ligera diferencia — hemos definido solo las propiedades dentro del constructor:

+ +
function Persona(nombrePila, apellido, edad, genero, intereses) {
+  this.nombre = {
+    nombrePila,
+    apellido
+  };
+  this.edad = edad;
+  this.genero = genero;
+  this.intereses = intereses;
+};
+ +

Todos los métodos están definidos en el prototipo del constructor. Por ejemplo:

+ +
Persona.prototype.saludo = function() {
+  alert('¡Hola! soy ' + this.nombre.nombrePila + '.');
+};
+ +
+

Nota: En el código fuente, también verá los métodos bio() y despedida() definidos. Más tarde verá cómo estos pueden ser heredados por otros constructores.

+
+ +

Digamos que quisieramos crear una clase de Profesor, como la que describimos en nuestra definición inicial orientada a objetos, que hereda todos los miembros de Persona, pero también incluye:

+ +
    +
  1. Una nueva propiedad, materia — esto contendrá la materia que el profesor enseña.
  2. +
  3. Un método actualizado de saludo(), que suena un poco más formal que el método estándar de saludo() — más adecuado para un profesor que se dirige a algunos estudiantes en la escuela.
  4. +
+ +

Definiendo un constructor Profesor()

+ +

Lo primero que tenemos que hacer es crear el constructor Profesor()  — añadimos lo siguiente tras el código existente:

+ +
function Profesor(nombrePila, apellido, edad, genero, intereses, materia) {
+  Person.call(this, nombrePila, apellido, edad, genero, intereses);
+
+  this.materia = materia;
+}
+ +

Esto es similar al constructor de Persona en muchos aspectos, pero hay algo extraño aquí que no hemos visto antes: la función call (). Esta función básicamente le permite llamar a una función definida en otro lugar, pero en el contexto actual.
+ El primer parámetro especifica el valor de this que desea utilizar al ejecutar la función, y los otros parámetros son aquellos que deben pasarse a la función cuando se invoca.

+ +

Queremos que el constructor Profesor() tome los mismos parámetros que el constructor Persona() del que está heredando, por lo que los especificamos todos como parámetros en la invocación call().

+ +

La última línea dentro del constructor simplemente define la nueva propiedad subject que los profesores tendrán y que las personas genéricas no tienen.

+ +

Como nota, podríamos haber simplemente hecho esto:

+ +
function Profesor(nombrePila, apellido, edad, genero, intereses, materia) {
+  this.nombre = {
+    nombrePila,
+    apellido
+  };
+  this.edad = edad;
+  this.genero = genero;
+  this.intereses = intereses;
+  this.materia = materia;
+}
+ +

Pero esto es solo definir las propiedades de nuevo, no heredarlas de Persona(), por lo que anula el punto de lo que estamos tratando de hacer. También lleva más líneas de código.

+ +

Heredando de un constructor sin parámetros

+ +

Nótese que si el constructor del cual se está heredando no toma los valores de sus propiedades de parámetros, no se necesita especificarlos como argumentos adicionales en call(). Por ejemplo, si se tuviera algo muy simple como esto:

+ +
function Brick() {
+  this.width = 10;
+  this.height = 20;
+}
+ +

Se podrían heredar las propiedades width y height haciendo esto (así como los otros pasos descritos a continuación, por supuesto):

+ +
function BlueGlassBrick() {
+  Brick.call(this);
+
+  this.opacity = 0.5;
+  this.color = 'blue';
+}
+ +

Nótese que solo especificamos this dentro de call() — no se requieren otros parámetros ya que no estamos heredando ninguna propiedad del padre que sea establecida por parámetros.

+ +

Estableciendo el prototipo de Profesor() y su referencia al constructor

+ +

Todo va bien hasta ahora, pero tenemos un problema. Definimos un nuevo constructor, y tiene una propiedad prototype, la cual por defecto solo contiene una referencia a la función constructor en sí misma. No contiene los métodos de la propiedad prototype del constructor Persona. Para ver esto, introduzca Object.getOwnPropertyNames(Profesor.prototype) ya sea en el campo de texto o en la consola de Javascript . Introdúzcalo nuevamente, reemplazando Profesor con Persona. El nuevo constructor tampoco hereda esos métodos. Para ver esto, compare los resultados de Persona.prototype.saludo and Profesor.prototype.saludo. Necesitamos obtener Profesor() para obtener los métodos definidos en el prototipo de Persona(). ¿Cómo lo hacemos?

+ +
    +
  1. Añade la siguiente línea debajo de tu adición anterior: +
    Profesor.prototype = Object.create(Persona.prototype);
    + Aquí es cuando nuestro amigo create() sale al rescate de nuevo. En este caso lo estamos usando para crear un nuevo objeto y hacerlo el valor de Profesor.prototype. El nuevo objeto tiene Persona.prototype como su prototipo y por lo tanto heredará, si y cuando lo necesite, todos los métodos disponibles en Persona.prototype.
  2. +
  3. Necesitamos hacer una cosa más antes de proseguir. Después de agregar la última línea, la propiedad constructor de  Profesor.prototype es ahora igual a Persona(), debido a que acabamos de asignar Profesor.prototype para que haga referencia a un objeto que hereda sus propiedades de Persona.prototype! Ahora prueba guardando tu código, carga la página en un explorador e intenta verificar en la consola el valor de  Profesor.prototype.constructor.
  4. +
  5. Esto puede volverse un problema, así que necesitamos corregirlo. Puedes hacerlo regresando a tu código y agregando la siguiente línea al final: +
    Profesor.prototype.constructor = Profesor;
    +
  6. +
  7. Ahora, si guardas y actualizas, el valor de Profesor.prototype.constructor debe regresar Profesor(), como se espera, además de que ahora estamos heredando de Persona()!
  8. +
+ +

Dándole a Profesor() un nuevo método saludo()

+ +

Para finalizar nuestro código, necesitamos definir un nuevo método saludo() en el constructor de Profesor().

+ +

La manera más fácil es definirlo en el prototipo de Profesor() — agrega lo siguiente al final de tu código:

+ +
Profesor.prototype.saludo = function() {
+  var prefijo;
+
+  if (this.genero === 'masculino' || this.genero === 'Masculino' || this.genero === 'm' || this.genero === 'M') {
+    prefijo = 'Sr.';
+  } else if (this.genero === 'female' || this.genero === 'Femenino' || this.genero === 'f' || this.genero === 'F') {
+    prefijo = 'Sra.';
+  } else {
+    prefijo = 'Sx.';
+  }
+
+  alert('Hola. Mi nombre es ' + prefijo + ' ' + this.nombre.apellido + ', y enseño ' + this.materia + '.');
+};
+ +

Esto muestra el saludo del profesor, el cual además utiliza un prefijo apropiado para su género, resuelto utilizando un bloque else-if.

+ +

Probando el ejemplo

+ +

Ahora que ha ingresado todo el código, intente creando una instancia de objeto desde Profesor() poniendo lo que sigue al final de su archivo (o algo similar a su elección):

+ +
var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
+ +

Ahora guarde y actualice, e intente accediendo a las propiedades y metodos de su nuevo teacher1 objecto, por ejemplo:

+ +
teacher1.name.first;
+teacher1.interests[0];
+teacher1.bio();
+teacher1.subject;
+teacher1.greeting();
+teacher1.farewell();
+ +

Esto deberia trabajar bien. Las consultas de las líneas 1, 2, 3, y 6 acceden a miembros heredados del genérico Person() constructor (clase). La consulta de la línea 4 accede un miembro que es disponible solamente en el mas especializado Teacher() constructor (clase). La consulta de la línea 5 accedería a un miembro desde Person(), excepto por el hecho que Teacher() tiene sus propios miembros con el mismo nombre, entonces la consulta accede a ese miembro.

+ +
+

Nota: Si tiene problemas con el funcionamiento, compare su código con nuestra versión final (vea corriendo en vivo también).

+
+ +

La técnica que mostramos aquí no es la única para crear herencia de clases en JavaScript, pero funciona OK, y le dá una buena idea acerca de cómo implementar herencia en JavaScript.

+ +

También estará interesado en verificar algo de las nuevas características de {{glossary("ECMAScript")}} que nos permiten hacer herencia mas claramente en JavaScript (véase Classes). No se cubrió todo aquí, como tampoco es soportado aún por todos los navegadores. Todo el otro código de constructores que se discutió aquí en estos artículos son soportados por IE9 o superior, y hay caminos para lograr superiores soportes que estos.

+ +

Un simple camino es usar una librería de JavaScript — la mayoría de las opciones mas populares tienen un facil ajuste de funcionalidad disponible para hacer herencia mas facil y rápido. CoffeeScript por ejemplo provee class, extends, etc.

+ +

Un ejercicio mas allá

+ +

En nuestra Sección teórica de POO, también incluimos una clase Student como un concepto, el cual hereda todas las características de Person, y también tiene un método diferende de greeting() que Person que es mas informal que el saludo de los profesores Teacher. Dele una mirada al saludo de los estudiantes, y trate de implementar su propio constructor de saludo Student() que herede todas las características de Person(), e implemente las diferentes funciones de saludo greeting().

+ +
+

Nota: Si tiene problemas resolviendo esto, dele una mirada a nuestra versión final (véala tambien funcionando ).

+
+ +

Resúmen de miembros objeto

+ +

To summarize, you've basically got three types of property/method to worry about:

+ +
    +
  1. Those defined inside a constructor function that are given to object instances. These are fairly easy to spot — in your own custom code, they are the members defined inside a constructor using the this.x = x type lines; in built in browser code, they are the members only available to object instances (usually created by calling a constructor using the new keyword, e.g. var myInstance = new myConstructor()).
  2. +
  3. Those defined directly on the constructor themselves, that are available only on the constructor. These are commonly only available on built-in browser objects, and are recognized by being chained directly onto a constructor, not an instance. For example, Object.keys().
  4. +
  5. Those defined on a constructor's prototype, which are inherited by all instances and inheriting object classes. These include any member defined on a Constructor's prototype property, e.g. myConstructor.prototype.x().
  6. +
+ +

If you are not sure which is which, don't worry about it just yet — you are still learning, and familiarity will come with practice.

+ +

ECMAScript 2015 Classes

+ +

ECMAScript 2015 introduces class syntax to JavaScript as a way to write reusable classes using easier, cleaner syntax, which is more similar to classes in C++ or Java. In this section we'll convert the Person and Teacher examples from prototypal inheritance to classes, to show you how it's done.

+ +
+

Note: This modern way of writing classes is supported in all modern browsers, but it is still worth knowing about how the underlying prototypal inheritance in case you work on a project that requires supporting a browser that doesn't support this syntax (most notably Internet Explorer).

+
+ +

Let's look at a rewritten version of the Person example, class-style:

+ +
class Person {
+  constructor(first, last, age, gender, interests) {
+    this.name = {
+      first,
+      last
+    };
+    this.age = age;
+    this.gender = gender;
+    this.interests = interests;
+  }
+
+  greeting() {
+    console.log(`Hi! I'm ${this.name.first}`);
+  };
+
+  farewell() {
+    console.log(`${this.name.first} has left the building. Bye for now!`);
+  };
+}
+
+ +

The class statement indicates that we are creating a new class. Inside this block, we define all the features of the class:

+ + + +

We can now instantiate object instances using the new operator, in just the same way as we did before:

+ +
let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);
+han.greeting();
+// Hi! I'm Han
+
+let leia = new Person('Leia', 'Organa', 19, 'female' ['Government']]);
+leia.farewell();
+// Leia has left the building. Bye for now
+
+ +
+

Note: Under the hood, your classes are being converted into prototypal Inheritance models — this is just syntactic sugar. But I'm sure you'll agree that it's easier to write.

+
+ +

Inheritance with class syntax

+ +

Above we created a class to represent a person. They have a series of attributes that are common to all people; in this section we'll create our specialized Teacher class, making it inherit from Person using modern class syntax. This is called creating a subclass or subclassing.

+ +

To create a subclass we use the extends keyword to tell JavaScript the class we want to base our class on.

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    this.name = {
+      first,
+      last
+    };
+
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+  // subject and grade are specific to Teacher
+  this.subject = subject;
+  this.grade = grade;
+  }
+}
+ +

We can make the code more readable by defining the super() operator as the first item inside the constructor(). This will call the parent class' constructor, and inherit the members we specify as parameters of super(), as long as they are defined there:

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+
+    // subject and grade are specific to Teacher
+    this.subject = subject;
+    this.grade = grade;
+  }
+}
+
+ +

When we instantiate Teacher object instances, we can now call methods and properties defined on both Teacher and Person, as we'd expect:

+ +
let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5);
+snape.greeting(); // Hi! I'm Severus.
+snape.farewell(); // Severus has left the building. Bye for now.
+snape.age // 58
+snape.subject; // Dark arts
+
+ +

Like we did with Teachers, we could create other subclasses of Person to make them more specialized without modifying the base class.

+ +
+

Note: You can find this example on GitHub as es2015-class-inheritance.html (see it live also).

+
+ +

Getters and Setters

+ +

There may be times when we want to change the values of an attribute in the classes we create or we don't know what the final value of an attribute will be. Using the Teacher example, we may not know what subject the teacher will teach before we create them, or their subject may change between terms.

+ +

We can handle such situations with getters and setters.

+ +

Let's enhance the Teacher class with getters and setters. The class starts the same as it was the last time we looked at it.

+ +

Getters and setters work in pairs. A getter returns the current value of the variable and its corresponding setter changes the value of the variable to the one it defines.

+ +

The modified Teacher class looks like this:

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+    // subject and grade are specific to Teacher
+    this._subject = subject;
+    this.grade = grade;
+  }
+
+  get subject() {
+    return this._subject;
+  }
+
+  set subject(newSubject) {
+    this._subject = newSubject;
+  }
+}
+
+ +

In our class above we have a getter and setter for the subject property. We use _  to create a separate value in which to store our name property. Without using this convention, we would get errors every time we called get or set. At this point:

+ + + +

The example below shows the two features in action:

+ +
// Check the default value
+console.log(snape.subject) // Returns "Dark arts"
+
+// Change the value
+snape.subject="Balloon animals" // Sets _subject to "Balloon animals"
+
+// Check it again and see if it matches the new value
+console.log(snape.subject) // Returns "Balloon animals"
+
+ +
+

Note: You can find this example on GitHub as es2015-getters-setters.html (see it live also).

+
+ +

When would you use inheritance in JavaScript?

+ +

Particularly after this last article, you might be thinking "woo, this is complicated". Well, you are right. Prototypes and inheritance represent some of the most complex aspects of JavaScript, but a lot of JavaScript's power and flexibility comes from its object structure and inheritance, and it is worth understanding how it works.

+ +

In a way, you use inheritance all the time. Whenever you use various features of a Web API , or methods/properties defined on a built-in browser object that you call on your strings, arrays, etc., you are implicitly using inheritance.

+ +

In terms of using inheritance in your own code, you probably won't use it often, especially to begin with, and in small projects. It is a waste of time to use objects and inheritance just for the sake of it when you don't need them. But as your code bases get larger, you are more likely to find a need for it. If you find yourself starting to create a number of objects that have similar features, then creating a generic object type to contain all the shared functionality and inheriting those features in more specialized object types can be convenient and useful.

+ +
+

Note: Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called delegation. Specialized objects delegate functionality to a generic object type.

+
+ +

When using inheritance, you are advised to not have too many levels of inheritance, and to keep careful track of where you define your methods and properties. It is possible to start writing code that temporarily modifies the prototypes of built-in browser objects, but you should not do this unless you have a really good reason. Too much inheritance can lead to endless confusion, and endless pain when you try to debug such code.

+ +

Ultimately, objects are just another form of code reuse, like functions or loops, with their own specific roles and advantages. If you find yourself creating a bunch of related variables and functions and want to track them all together and package them neatly, an object is a good idea. Objects are also very useful when you want to pass a collection of data from one place to another. Both of these things can be achieved without use of constructors or inheritance. If you only need a single instance of an object, then you are probably better off just using an object literal, and you certainly don't need inheritance.

+ +

Alternativas para extender la cadena del prototipos

+ +

En JavaScript, hay varias maneras diferentes de extender el prototipo de un objeto aparte de lo que hemos mostrado anteriormente. Para saber más sobre las otras formas, visite nuestro artículo Herencia y la cadena de prototipos.

+ +

Resumen

+ +

Este artículo ha cubierto el resto de la teoría y sintaxis central de OOJS que creemos que debería conocer ahora. En este punto debe entender los conceptos básicos de objetos JavaScript y POO, prototipos y herencia de prototipos, cómo crear clases (constructores) e instancias de objetos, añadir características a las clases y crear subclases que heredan de otras clases.

+ +

En el siguiente artículo veremos cómo trabajar con JavaScript Object Notation (JSON), un formato común de intercambio de datos escrito con objetos JavaScript.

+ +

Véase también

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}

+ +

En éste módulo

+ + diff --git a/files/es/learn/javascript/objects/json/index.html b/files/es/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..09009165cf --- /dev/null +++ b/files/es/learn/javascript/objects/json/index.html @@ -0,0 +1,339 @@ +--- +title: Trabajando con JSON +slug: Learn/JavaScript/Objects/JSON +tags: + - Arreglos + - Artículo + - Guía + - JSON + - Objetos + - Parsing + - Principiante + - Stringifying + - Tutorial +translation_of: Learn/JavaScript/Objects/JSON +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}
+ +

JavaScript Object Notation (JSON) es un formato basado en texto estándar para representar datos estructurados en la sintaxis de objetos de JavaScript. Es comúnmente utilizado para transmitir datos en aplicaciones web (por ejemplo: enviar algunos datos desde el servidor al cliente, así estos datos pueden ser mostrados en páginas web, o vice versa). Se enfrentará a menudo con él, así que este artículo le entrega todo lo que necesita saber para trabajar con JSON utilizando JavaScript, incluyendo el análisis JSON para acceder a los datos en su interior, y cómo crear JSON.

+ + + + + + + + + + + + +
Prerrequisitos:Alfabetismo computacional básico, una comprensión básica de HTML y CSS, familiaridad con los temas básicos de JavaScript (vea First steps y Building blocks) y OOJS básico (vea Introduction to objects).
Objetivo:Entender cómo trabajar con datos almacenados en JSON, y crear objetos JSON propios.
+ +

¿Qué es realmente JSON?

+ +

{{glossary("JSON")}} es un formato de datos basado en texto que sigue la sintaxis de objeto de JavaScript, popularizado por Douglas Crockford. Aunque es muy parecido a la sintaxis de objeto literal de JavaScript, puede ser utilizado independientemente de JavaScript, y muchos entornos de programación poseen la capacidad de leer (convertir; parsear) y generar JSON.

+ +

Los JSON son cadenas - útiles cuando se quiere transmitir datos a través de una red. Debe ser convertido a un objeto nativo de JavaScript cuando se requiera acceder a sus datos. Ésto no es un problema, dado que JavaScript posee un objeto global JSON que tiene los métodos disponibles para convertir entre ellos.

+ +
+

Nota: Convertir una cadena a un objeto nativo se denomina parsing, mientras que convertir un objeto nativo a una cadena para que pueda ser transferido a través de la red se denomina stringification.

+
+ +

Un objeto JSON puede ser almacenado en su propio archivo, que es básicamente sólo un archivo de texto con una extension .json, y una {{glossary("MIME type")}} de application/json.

+ +

Estructura del JSON

+ +

Como se describió previamente, un JSON es una cadena cuyo formato recuerda al de los objetos literales JavaScript. Es posible incluir los mismos tipos de datos básicos dentro de un JSON que en un objeto estándar de JavaScript - cadenas, números, arreglos, booleanos, y otros literales de objeto. Esto permite construir una jerarquía de datos, como ésta:

+ +
{
+  "squadName": "Super hero squad",
+  "homeTown": "Metro City",
+  "formed": 2016,
+  "secretBase": "Super tower",
+  "active": true,
+  "members": [
+    {
+      "name": "Molecule Man",
+      "age": 29,
+      "secretIdentity": "Dan Jukes",
+      "powers": [
+        "Radiation resistance",
+        "Turning tiny",
+        "Radiation blast"
+      ]
+    },
+    {
+      "name": "Madame Uppercut",
+      "age": 39,
+      "secretIdentity": "Jane Wilson",
+      "powers": [
+        "Million tonne punch",
+        "Damage resistance",
+        "Superhuman reflexes"
+      ]
+    },
+    {
+      "name": "Eternal Flame",
+      "age": 1000000,
+      "secretIdentity": "Unknown",
+      "powers": [
+        "Immortality",
+        "Heat Immunity",
+        "Inferno",
+        "Teleportation",
+        "Interdimensional travel"
+      ]
+    }
+  ]
+}
+ +

Si se carga este objeto en un programa de JavaScript, convertido (parseado) en una variable llamada superHeroes por ejemplo, se podría acceder a los datos que contiene utilizando la misma notación de punto/corchete que se revisó en el artículo JavaScript object basics. Por ejemplo:

+ +
superHeroes.homeTown
+superHeroes['active']
+ +

Para acceder a los datos que se encuentran más abajo en la jerarquía, simplemente se debe concatenar los nombres de las propiedades y los índices de arreglo requeridos. Por ejemplo, para acceder al tercer superpoder del segundo héroe registrado en la lista de miembros, se debería hacer esto: 

+ +
superHeroes['members'][1]['powers'][2]
+ +
    +
  1. Primero el nombre de la variable — superHeroes.
  2. +
  3. Dentro de esta variable para acceder a la propiedad members utilizamos ["members"].
  4. +
  5. members contiene un arreglo poblado por objetos. Para acceder al segundo objeto dentro de este arreglo se utiliza [1].
  6. +
  7. Dentro de este objeto, para acceder a la propiedad powers utilizamos ["powers"].
  8. +
  9. Dentro de la propiedad powers existe un arreglo que contiene los superpoderes del héroe seleccionado. Para acceder al tercer superpoder se utiliza [2].
  10. +
+ +
+

Nota: El JSON previamente visto se encuentra disponible dentro de una variable en el ejemplo JSONTest.html (vea el código fuente). Intente cargarlo y luego acceder a los datos contenidos en la variable por medio de la consola JavaScript de su navegador.

+
+ +

Arreglos como JSON

+ +

Anteriormente se mencionó que el texto JSON básicamente se parece a un objeto JavaScript, y esto es en gran parte cierto. La razón de esto es que un arreglo es también un JSON válido, por ejemplo:

+ +
[
+  {
+    "name": "Molecule Man",
+    "age": 29,
+    "secretIdentity": "Dan Jukes",
+    "powers": [
+      "Radiation resistance",
+      "Turning tiny",
+      "Radiation blast"
+    ]
+  },
+  {
+    "name": "Madame Uppercut",
+    "age": 39,
+    "secretIdentity": "Jane Wilson",
+    "powers": [
+      "Million tonne punch",
+      "Damage resistance",
+      "Superhuman reflexes"
+    ]
+  }
+]
+ +

Éste es un JSON perfectamente válido. Para acceder a esta version convertida se debe comenzar con un índice de arreglo, por ejemplo[0]["powers"][0].

+ +

Otras notas

+ + + +

Aprendizaje activo: Trabajando a través de un ejemplo de JSON

+ +

A continuación se muestra un ejemplo de cómo podemos utilizar algunos datos JSON en un sitio web.

+ +

Para comenzar

+ +

Haga una copia local de los archivos heroes.html y style.css. El último contiene un CSS simple para dar estilo a la página, mientras el primero contiene un HTML muy sencillo:

+ +
<header>
+</header>
+
+<section>
+</section>
+ +

Además de un elemento {{HTMLElement("script")}} que contiene el código JavaScript que se escribirá en este ejercicio. En este momento sólo contiene dos líneas, que hacen referencia a los elementos {{HTMLElement("header")}} y {{HTMLElement("section")}} y los almacena en variables:

+ +
const header = document.querySelector('header');
+const section = document.querySelector('section');
+ +

Los datos JSON se encuentran disponibles en GitHub en el siguiente enlace: https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json.

+ +

Los datos se cargarán en esta página y se desplegarán a través de la manipulación del DOM de esta forma:

+ +

+ +

Obteniendo el JSON

+ +

Para obtener el JSON se utilizará un API llamado {{domxref("XMLHttpRequest")}} (a menudo llamado XHR). Éste en un objeto JavaScript muy útil que permite realizar solicitudes de red para recuperar recursos desde un servidor vía JavaScript (por ejemplo: imágenes, texto, JSON, incluso código HTML), con lo que es posible actualizar pequeñas secciones de contenido sin tener que volver a cargar la página entera. Con ello se obtienen páginas web más interactivas, pero está fuera del alcance de este artículo entrar en detalle.

+ +
    +
  1. Para empezar, se debe almacenar la URL del JSON que se quiere recuperar en una variable. Agregue lo siguiente al final del código JavaScript: +
    const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
    +
  2. +
  3. Para crear una solicitud, se necesita crear una nueva instancia de objeto de solicitud desde el constructorXMLHttpRequest, utilizando la palabra clave new. Agregue lo siguiente a continuación de la última línea: +
    const request = new XMLHttpRequest();
    +
  4. +
  5. Ahora es necesario abrir una nueva solicitud utilizando el método open(). Agregue la siguiente línea: +
    request.open('GET', requestURL);
    + +

    Esto requiere al menos dos parámetros — Existen otros parámetros opcionales disponibles. Sólo se requieren los dos obligatorios para este ejemplo:

    + +
      +
    • El método HTTP a usar cuando se hace una solicitud en red. En este caso GET es adecuado, dado que sólo se estan recuperando algunos datos simples.
    • +
    • La URL a la que se realiza la solicitud — esta es la URL del archivo que se almacenó antes.
    • +
    +
  6. +
  7. Luego, agregue las siguientes dos lineas — establecemos el responseType a JSON, de esta forma ese XHR sabe que el servidor estará retornando JSON y que esto debería ser convertido en segundo plano en un objeto JavaScript. Entonces se envía la solicitud con el método send(): +
    request.responseType = 'json';
    +request.send();
    +
  8. +
  9. La última parte de esta sección comprende la espera por la respuesta a retornar desde el servidor y luego, manejarla. Agregue el siguiente código bajo el código previo: +
    request.onload = function() {
    +  const superHeroes = request.response;
    +  populateHeader(superHeroes);
    +  showHeroes(superHeroes);
    +}
    +
  10. +
+ +

En este punto se está almacenando la respuesta a la solicitud (disponible en la propiedad response) en una variable llamada superHeroes; esta variable ahora contendrá el objeto JavaScript basado en el JSON. Luego se pasa el objeto como argumento a dos funciones — la primera llenará el <header> con los datos correctos, mientras la segunda creará una tarjeta de información para cada héroe en el equipo y la insertará en <section>.

+ +

Se ha contenido el código en un manejador de eventos que se activa cuando se dispara el evento de carga (ver onload) — esto es porque el evento de carga se dispara cuando la respuesta ha sido retornada de forma exitosa; de esta manera se garantiza que request.response estará disponible cuando se intente hacer algo con ella.

+ +

Poblando el encabezado

+ +

Se han obtenido los datos desde el JSON y convertidos en un objeto de JavaScript. Ahora, se utilizarán estos datos escribiendo las dos funciones que fueron referenciadas previamente. Antes que todo, agregue la siguiente definición de función a continuación del código previo:

+ +
function populateHeader(jsonObj) {
+  const myH1 = document.createElement('h1');
+  myH1.textContent = jsonObj['squadName'];
+  header.appendChild(myH1);
+
+  const myPara = document.createElement('p');
+  myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed'];
+  header.appendChild(myPara);
+}
+ +

Se ha llamado al parámetro jsonObj, para recordar que este es un objeto JavaScript originado desde un JSON. Primero se crea un elemento {{HTMLElement("h1")}} con createElement(), se asigna su textContent igual a la propiedad squadName del objeto, luego se agrega al encabezado utilizandoappendChild(). A continuación se realiza una operación muy parecida en un párrafo: se crea, se asigna su contenido de texto y se agrega al encabezado. La única diferencia es que su texto se asigna a una cadena concatenada que contiene las propiedades homeTown y formed del objeto.

+ +

Creación de las tarjetas de información del héroe

+ +

Luego, agregue la siguiente función al final del código, que crea y muestra las tarjetas de los superhéroes:

+ +
function showHeroes(jsonObj) {
+  const heroes = jsonObj['members'];
+
+  for (var i = 0; i < heroes.length; i++) {
+    const myArticle = document.createElement('article');
+    const myH2 = document.createElement('h2');
+    const myPara1 = document.createElement('p');
+    const myPara2 = document.createElement('p');
+    const myPara3 = document.createElement('p');
+    const myList = document.createElement('ul');
+
+    myH2.textContent = heroes[i].name;
+    myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
+    myPara2.textContent = 'Age: ' + heroes[i].age;
+    myPara3.textContent = 'Superpowers:';
+
+    const superPowers = heroes[i].powers;
+    for (var j = 0; j < superPowers.length; j++) {
+      const listItem = document.createElement('li');
+      listItem.textContent = superPowers[j];
+      myList.appendChild(listItem);
+    }
+
+    myArticle.appendChild(myH2);
+    myArticle.appendChild(myPara1);
+    myArticle.appendChild(myPara2);
+    myArticle.appendChild(myPara3);
+    myArticle.appendChild(myList);
+
+    section.appendChild(myArticle);
+  }
+}
+ +

Para empezar, se almacena la propiedad members del objeto JavaScript en una nueva variable. Este arreglo contiene múltiples objetos que contienen la información para cada héroe.

+ +

A continuación, se utiliza un ciclo for para recorrer cada objeto en el arreglo. Para cada uno:

+ +
    +
  1. Se crean varios elementos nuevos: un<article>, un <h2>, tres <p>s, y una <ul>.
  2. +
  3. Se asigna al <h2> para que muestre el name del héroe.
  4. +
  5. Se completan los tres párrafos con su secretIdentity, age, y una línea que diga "Superpowers:" para introducir la información de la lista.
  6. +
  7. Se almacena la propiedad powers en otra variable nueva llamada superPowers — que contiene un arreglo que lista los superpoderes del héroe actual.
  8. +
  9. Para recorrer los superpoderes del héroe, se utiliza otro ciclo for  — para cada uno se crea un elemento <li>, se asigna el superpoder a él y luego se pone el listItem dentro del elemento <ul>  (myList) utilizando appendChild().
  10. +
  11. Lo último es agregar los <h2>, <p>s, y <ul> dentro del <article> (myArticle), luego se agrega <article> dentro de <section>. El orden en que las cosas son agregadas es importante, dado que este es el orden en el que aparecerán dentro del HTML.
  12. +
+ +
+

Nota: Si tiene problemas en lograr que el ejemplo funcione, intente con el código fuente heroes-finished.html (vea también running live.)

+
+ +
+

Nota: Si encuentra dificultades en seguir la notacion de punto/corchete que se utiliza para acceder a los objetos de JavaScript, puede ser útil tener el archivo superheroes.json abierto en otra pestaña o en su editor de texto, y revisarlo mientras observa el código JavaScript. También puede referirse al artículo JavaScript object basics para mayor información sobre la notación de punto y corchete.

+
+ +

Conversiones entre objetos y texto

+ +

El ejemplo anterior era simple en términos de acceder al objeto JavaScript, porque se programó la solicitud XHR para convertir el JSON de respuesta directamente en un objeto de JavaScript utilizando:

+ +
request.responseType = 'json';
+ +

En algunas ocasiones, se recibirá una cadena JSON sin procesar, y será necesario convertirla en un objeto. Y cuando sea necesario enviar un objeto Javascript a través de la red, será necesario convertirlo a un JSON (una cadena) antes de ser enviado. Afortunadamente, estos dos problemas son muy comunes en el desarrollo web por lo que un objeto JSON integrado está disponible en los navegadores, que contiene los siguientes dos métodos:

+ + + +

El primer método se puede observar en el ejemplo heroes-finished-json-parse.html (vea el código fuente) — que realiza exactamente lo mismo que el ejemplo que se construyó previamente, excepto porque se determinó que el XHR devolviera el texto JSON sin procesar, luego se utiliza parse() para convertirlo en un objeto JavaScript. El extracto del código es el siguiente:

+ +
request.open('GET', requestURL);
+request.responseType = 'text'; // recibimos una cadena de tipo "string"
+request.send();
+
+request.onload = function() {
+  const superHeroesText = request.response; // cogemos la cadena de response
+  const superHeroes = JSON.parse(superHeroesText); // la convertimos a objeto
+  populateHeader(superHeroes);
+  showHeroes(superHeroes);
+}
+ +

Como es de suponer, stringify() trabaja de la forma opuesta. Intente ingresar las siguientes líneas en la consola de JavaScript de su navegador para verlo en acción:

+ +
const myJSON = { "name": "Chris", "age": "38" };
+myJSON
+const myString = JSON.stringify(myJSON);
+myString
+ +

En este caso, se ha creado un objeto JavaScript, luego se comprueba lo que contiene, y entonces se convierte en una cadena JSON utilizando stringify() — guardando el valor retornado en una variable nueva  — y comprobándolo nuevamente.

+ +

Resumen

+ +

En este artículo se ha entregado una guía simple para utilizar JSON en sus programas, incluyendo cómo crear y leer JSON, y cómo acceder a los datos almacenados en él. En el artículo siguiente se verá JavaScript orientado a objetos.

+ +

Vea también

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}

diff --git a/files/es/learn/javascript/objects/object-oriented_js/index.html b/files/es/learn/javascript/objects/object-oriented_js/index.html new file mode 100644 index 0000000000..5eb023c685 --- /dev/null +++ b/files/es/learn/javascript/objects/object-oriented_js/index.html @@ -0,0 +1,307 @@ +--- +title: JavaScript orientado a objetos para principiantes +slug: Learn/JavaScript/Objects/Object-oriented_JS +tags: + - Aprender + - Artículo + - Constructor + - Crear + - Create + - JSOO + - JavaScript + - OOJS + - OOP + - Object + - Objeto + - Orientado a Objeto + - Principiante + - Programación orientada a objetos + - instance + - instanciar + - 'l10n:priority' +translation_of: Learn/JavaScript/Objects/Object-oriented_JS +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}
+ +

Con lo básico fuera del camino, nos enfocaremos en Javascript Orientado a Objetos (JSOO) — este artículo presenta una descripción básica de la teoría de la Programación Orientada a Objetos (POO), luego explora cómo Javascript emula classes de objetos via funciones constructoras, y cómo crea instancias de objetos.

+ + + + + + + + + + + + +
Prerequisitos:Conocimientos básicos de computación, entendimiento básico de HTML y CSS, familiaridad con las bases de Javascript (ver Primeros pasos con JavaScript y Bloques de construcción JavaScript) y las bases de JSOO (ver Introducción a objetos).
Objetivo: +

Entender la teoría base de la programación orientada a objetos, como se relaciona esta con JavaScript ("todo es un objeto"), y como crear constructores e instacias de objetos.

+
+ +

Programacion Orientada a Objetos— lo básico

+ +

Para empezar, daremos una descripción simple y de alto nivel acerca de lo que es la Programación Orientada a Objetos (POO). Decimos simple, porque la POO puede volverse complicada rápidamente, y darte un tratamiento completo ahora, probablemente podría confundirte más que ayudar. La idea básica de la POO es que usamos objetos para modelar cosas del mundo real que queremos representar en nuestros programas, y/o proveemos una simple manera para acceder a la funcionalidad que, de otra manera, sería difícil o imposible de usar.

+ +

Los objetos pueden contener información y código relacionados, los cuales representan información acerca de lo que estás tratando de modelar, y la funcionalidad o comportamiento que deseas que tenga.  Los datos de un Objeto (y frecuentemente, también las funciones) se pueden almacenar ordenadamente (la palabra oficial es encapsular) dentro del paquete de un objeto (al que se puede asignar un nombre específico, llamado a veces espacio de nombres), haciéndolo fácil de estructurar y acceder; los objetos también se usan comúnmente como almacenes de datos que se pueden enviar fácilmente a través de la red.

+ +

Definiendo una plantilla de objeto

+ +

Vamos a considerar un sencillo programa que muestra información sobre estudiantes y profesores en una escuela. Aquí daremos un vistazo a la POO (Programación Orientada a Objetos) en general, no en el contexto de algún lenguaje de programación específico.

+ +

Para empezar, podríamos volver a ver al objeto Persona de nuestro artículo de primeros objetos, que define los datos generales y funcionalidades de una persona. Hay muchas cosas que podrías saber acerca de una persona (su dirección, estatura, tamaño de calzado, perfil de ADN, número de pasaporte, rasgos significativos de su personalidad...), pero, en este caso, solo estamos interesados en mostrar su nombre, edad, género e intereses, además de una pequeña introducción sobre este individuo basada en los datos anteriores. También queremos que sea capaz de saludar. 

+ +

Esto es conocido como abstracción —  crear un modelo simple de algo complejo que represente sus aspectos más importantes y que sea fácil de manipular para el propósito de nuestro programa.

+ +

+ +

En algunos lenguajes de POO, esta definición de tipo de objeto se la llama class (JavaScript utiliza diferentes mecanismos y terminologías, como verás a continuación) — esto no es en realidad un objeto, en vez de esto es un modelo que define las características que un objeto debería tener.

+ +

Creando objetos

+ +

Partiendo de nuestra clase, podemos crear instancias de objetos — objetos que contienen los datos y funcionalidades definidas en la clase original. Teniendo a nuestra clase Persona, ahora podemos crear gente con características más específicas: 

+ +

+ +

Cuando una instancia del objeto es creada a partir de una clase, se ejecuta la función constructora (constructor en inglés) de la clase para crearla. El proceso de crear una instancia del objeto desde una clase se llama instanciación.

+ +

Clases especializadas

+ +

En este caso nosotros no queremos personas genericas — queremos docentes y estudiantes, que son los dos tipos más específicos de personas. En POO, podemos crear nuevas clases basadas en otras clases, estas nuevas clases secundarias se pueden hacer para  heredar los datos y código de su clase primaria, de modo que pueden reutilizar la funcionalidad común a todos los tipos de objetos en lugar de tener que duplicarla. Cuando la funcionalidad difiere entre clases, puedes definir funciones especializadas directamente en ellas según sea necesario.

+ +

+ +

Esto es realmente útil, los profesores y los estudiantes comparten muchas características comunes como el nombre, el género y la edad, por lo que es conveniente tener que definir esas características solo una vez. También puedes definir la misma característica por separado en diferentes clases, ya que cada definición de esa característica estará en un espacio de nombres diferente. Por ejemplo, el saludo de un estudiante puede tener la forma "Yo, soy [Nombre]" (por ejemplo, Yo, soy Sam), mientras que un profesor puede usar algo más formal, como "Hola, mi nombre es [Prefix] [lastName], y enseño [Asunto] ". (Por ejemplo, Hola, mi nombre es Sr. Griffiths, y yo enseño Química).

+ +
+

Nota:  la palabra elegante para la capacidad de múltiples tipos de objetos de implementar la misma funcionalidad es polimorfismo. Por si acaso te preguntabas.

+
+ +

Ahora puedes crear instancias de objetos de las clases "hijo". Por ejemplo:

+ +

+ +

En el resto del articulo, comenzaremos a ver como podemos practicar la teoría de POO en JavaScript.

+ +

Constructores e instancias de objetos

+ +

Algunas personas sostienen que JavaScript no es un verdadero lenguaje orientado a objetos — por ejemplo, su enunciado class es sólo azúcar sintáctica sobre la herencia prototípica existente y no es una class en el sentido tradicional. JavaScript, utiliza funciones especiales llamadas funciones constructoras para definir objetos y sus características. Son útiles porque a menudo te encontrarás con situaciones en las que no sabes cuántos objetos crearás; los constructores proporcionan los medios para crear tantos objetos como necesites de una manera efectiva, adjuntando datos y funciones a ellos según sea necesario.

+ +

Cuando se crea una nueva instancia del objeto a partir de una función constructora, su funcionalidad central (tal como se define en su prototipo, que exploraremos en el artículo Prototipos de objetos) no se copia en el nuevo objeto como lenguajes OO "clásicos", sino que la funcionalidad está vinculada a través de una cadena de referencia llamada cadena prototipo. Así que esto no es una verdadera instanciación, estrictamente hablando, JavaScript usa un mecanismo diferente para compartir funcionalidad entre objetos.

+ +
+

Nota: no ser "POO clásica" no es necesariamente algo malo; Como se mencionó anteriormente, la POO puede ser muy compleja muy rápidamente, y JavaScript tiene algunas agradables formas de aprovechar las características de la OO sin tener que profundizar demasiado en ello.

+
+ +

Exploremos la creación de clases a través de constructores y la creación de instancias de objetos a partir de ellas en JavaScript. En primer lugar, nos gustaría que hicieras una nueva copia local del archivo oojs.html que vimos en nuestro primer artículo de Objetos.

+ +

Un ejemplo simple

+ +
    +
  1. Comencemos por ver cómo puedes definir una persona con una funcion normal. Agrega esta funcion dentro del elemento script: + +
    function createNewPerson(name) {
    +  var obj = {};
    +  obj.name = name;
    +  obj.greeting = function() {
    +    alert('Hi! I\'m ' + this.name + '.');
    +  };
    +  return obj;
    +}
    +
  2. +
  3. Ahora puedes crear una nueva persona llamando a esta funcion — prueba con las siguientes lineas en la consola Javascript de tu navegador: +
    var salva = createNewPerson('Salva');
    +salva.name;
    +salva.greeting();
    + Esto funciona bastante bien, pero es un poco largo; si sabemos que queremos crear un objeto, ¿por qué necesitamos crear explícitamente un nuevo objeto vacío y devolverlo? Afortunadamente, JavaScript nos proporciona un práctico acceso directo, en forma de funciones constructoras — ¡hagamos una ahora!
  4. +
  5. Reemplaza tu función anterior por la siguiente: +
    function Person(name) {
    +  this.name = name;
    +  this.greeting = function() {
    +    alert('Hi! I\'m ' + this.name + '.');
    +  };
    +}
    +
  6. +
+ +

La función constructora es la versión de JavaScript de una clase. Notarás que tiene todas las características que esperas en una función, aunque no devuelve nada o crea explícitamente un objeto — básicamente sólo define propiedades y métodos. Verás que la palabra clave this se está usando aquí también — es básicamente decir que cuando se crea una de estas instancias de objeto, la propiedad name del objeto será igual al valor del nombre pasado a la llamada del constructor, y el método greeting() usará también el valor del nombre pasado a la llamada del constructor.

+ +
+

Nota: Un nombre de función constructora generalmente comienza con una letra mayúscula — esta convención se utiliza para hacer que las funciones constructoras sean más fáciles de reconocer en el código.

+
+ +

Entonces, ¿cómo llamamos a un constructor para crear algunos objetos?

+ +
    +
  1. Agrega las siguientes líneas debajo de tu código anterior: +
    var person1 = new Person('Bob');
    +var person2 = new Person('Sarah');
    +
  2. +
  3. Guarda el código y vuelve a cargarlo en el navegador, e intenta ingresar las siguientes líneas en la consola Javascript : +
    person1.name
    +person1.greeting()
    +person2.name
    +person2.greeting()
    +
  4. +
+ +

¡Guaw! Ahora veras que tenemos dos nuevos objetos, cada uno de los cuales está almacenado en un espacio de nombres diferente: para acceder a sus propiedades y métodos, debes llamarlos como person1 o  person2; están cuidadosamente empaquetados para que no entren en conflicto con otras funciones. Sin embargo, tienen disponible la misma propiedad name y el método greeting(). Ten en cuenta que están utilizando su propio name que se les asignó cuando se crearon; esta es una razón por la cual es muy importante usar this, para que usen sus propios valores, y no algún otro valor.

+ +

Veamos nuevamente las llamadas del constructor:

+ +
var person1 = new Person('Bob');
+var person2 = new Person('Sarah');
+ +

En cada caso, la  palabra clave new se usa para indicarle al navegador que queremos crear una nueva instancia del objeto, seguida del nombre de la función con sus parámetros requeridos entre paréntesis, y el resultado se almacena en una variable — muy similar a cómo se llama a una función estándar. Cada instancia se crea de acuerdo con esta definición:

+ +
function Person(name) {
+  this.name = name;
+  this.greeting = function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  };
+}
+ +

Una vez creados los nuevos objetos, las variables person1 y person2 contienen los siguientes objetos:

+ +
{
+  name: 'Bob',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+
+{
+  name: 'Sarah',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+ +

Ten en cuenta que cuando llamamos a nuestra función constructora, estamos definiendo greeting() cada vez, lo cual no es lo ideal. Para evitar esto, podemos definir funciones en el prototipo, que veremos más adelante.

+ +

Creando nuestro constructor final

+ +

El ejercicio que vimos anteriormente fue solo un ejemplo simple para comenzar. Ahora crearemos nuestra función constructor Person() final.

+ +
    +
  1. Elimina el código que insertaste hasta ahora y agrega este constructor de reemplazo; este es exactamente el mismo que el ejemplo simple del principio, con un poco más de complejidad: +
    function Person(first, last, age, gender, interests) {
    +  this.name = {
    +    'first': first,
    +    'last' : last
    +  };
    +  this.age = age;
    +  this.gender = gender;
    +  this.interests = interests;
    +  this.bio = function() {
    +    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    +  };
    +  this.greeting = function() {
    +    alert('Hi! I\'m ' + this.name.first + '.');
    +  };
    +}
    +
  2. +
  3. Ahora, agrega la siguiente línea para crear una instancia del objeto: +
    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
    +
  4. +
+ +

Ahora verás que puedes acceder a las propiedades y métodos justo como lo hiciste anteriormente — intenta esto en tu consola JS:

+ +
person1['age']
+person1.interests[1]
+person1.bio()
+// etc.
+ +
+

Nota: Si tienes problemas para lograr que funcione, puedes comparar tu código con nuestra versión — ve oojs-class-finished.html (también lo puedes ver corriendo en vivo).

+
+ +

Ejercicios adicionales

+ +

Para empezar, intenta añadir un par de líneas de creación de objetos propias, y trata de obtener y asignar valores a los miembros de las instancias del objeto.

+ +

Además, hay un par de problemas con nuestro método bio() — la salida siempre incluye el pronombre "He", incluso para personas de otros géneros. Y bio solamente incluye dos intereses, sin importar la cantidad que hay en el arreglo interests. ¿Podrías corregir esto en la definición de la clase (constructor)? Puedes poner cualquier código dentro de un constructor (probablemente necesites algunos condicionales y un bucle). Piensa como se deben estructurar las declaraciones dependiendo del género, y de la cantidad de intereses.

+ +
+

Note: Si estás atascado, hay una respuesta en nuestro repositorio de GitHub (see it live) — igualmente ¡intentea resolverla primero!

+
+ +

Otras formas de crear instancias de objetos

+ +

Hasta ahora hemos visto dos diferentes formas de crear una instancia de objeto — declarando un objeto literal, y usando una función constructora (ver arriba).

+ +

Esto tiene sentido, pero hay otras formas — se muestran aquí para que te vayas familiarizando en caso de encontrarte con ellas.

+ +

El constructor Object()

+ +

Antes que nada, puedes usar el constructor Object() para crear un nuevo objeto. Si, incluso objetos genéricos tienen un constructor que genera un objeto vacío.

+ +
    +
  1. Intenta ingresar este código en la consola JavaScript de tu navegador: +
    var person1 = new Object();
    +
  2. +
  3. Esto guarda un objeto vacío en la variable person1. Luego pueded agregar propiedades y métodos a este objeto usando la notación de punto (.) o de corchetes (['']); prueba estos ejemplos en tu consola: +
    person1.name = 'Chris';
    +person1['age'] = 38;
    +person1.greeting = function() {
    +  alert('Hi! I\'m ' + this.name + '.');
    +};
    +
  4. +
  5. También puedes pasar un objeto literal como parámetro al constructor Object(), para precargarlo con propiedades/métodos. Prueba esto en tu consola: +
    var person1 = new Object({
    +  name: 'Chris',
    +  age: 38,
    +  greeting: function() {
    +    alert('Hi! I\'m ' + this.name + '.');
    +  }
    +});
    +
  6. +
+ +

Usando el método create()

+ +

Los constructores te pueden ayudar a ordenar tu código — puedes crear constructores en un lugar, y luego crear instancias cuando sean necesarias.

+ +

Sin embargo, algunas personas prefieren crear instancias de objetos sin crear antes constructores, especialmente si van a crear solamente pocas instancias de un objeto.

+ +

JavaScript tiene un método llamado create() que permite hacer esto. Con este método puedes crear un nuevo objeto basado en cualquier otro objeto existente.

+ +
    +
  1. Con tu ejercicio de la sección anterior cargado en el navegador, prueba esto en tu consola JavaScript +
    var person2 = Object.create(person1);
    +
  2. +
  3. Y ahora prueba esto: +
    person2.name
    +person2.greeting()
    +
  4. +
+ +

Verás que person2 fue creado basado en person1 — tiene las mismas propiedades y métodos.

+ +

Una limitación del método create() es que no está soportado por el navegador IE8. Por lo que los constructores serán más efectivos sin necesitas soportar navegadores antiguos.

+ +

Más tarde, exploraremos en detalle los efectos de create().

+ +

Resumen

+ +

Este artículo provee una visión simplificada de la teoría de la orientación a objetos — esta no es toda la historia, pero te da una idea de con que estamos lidiando aquí. Adicionalmente, empezamos a ver como JavaScript está relacionado y difiere de la orientación a objetos "clásica", cómo usamos funciones constructoras para implementar clases en JavaScript, y diferentes formas de generar instancias de objetos.

+ +

En el próximo artículo, exploraremos los prototipos de objeto JavaScript.

+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}

+ +

En este modulo

+ + diff --git a/files/es/learn/javascript/objects/object_prototypes/index.html b/files/es/learn/javascript/objects/object_prototypes/index.html new file mode 100644 index 0000000000..852dd5e70e --- /dev/null +++ b/files/es/learn/javascript/objects/object_prototypes/index.html @@ -0,0 +1,282 @@ +--- +title: Prototipos de objetos +slug: Learn/JavaScript/Objects/Object_prototypes +tags: + - Aprender + - Artículo + - Cadena de Prototipos + - Constructor + - JavaScript + - Objetos + - Principiante + - Prototipo + - create() +translation_of: Learn/JavaScript/Objects/Object_prototypes +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}
+ +

Los prototipos son un mecanismo mediante el cual los objetos en JavaScript heredan características entre sí. En este artículo, explicaremos como funcionan los prototipos y también cómo se pueden usar las propiedades de estos para añadir métodos a los contructores existentes.

+ + + + + + + + + + + + +
Prerrequisitios:Conocer las funciones en Javascript, conocimientos básicos de Javascript (ver Primeros Pasos y Building blocks) y Javascript orientado a Objetos (ver Introducción a Objetos).
Objetivo:Comprender los prototipos de objectos de Javascript, cómo funciona la cadena de prototype, y cómo añadir nuevos métodos a la propiedad prototype.
+ +

¿Un lenguaje basado en prototipos?

+ +

JavaScript es a menudo descrito como un lenguaje basado en prototipos - para proporcionar mecanismos de herencia, los objetos pueden tener un objeto prototipo, el cual actúa como un objeto plantilla que hereda métodos y propiedades.

+ +

Un objeto prototipo del objeto puede tener a su vez otro objeto prototipo, el cual hereda métodos y propiedades, y así sucesivamente. Esto es conocido con frecuencia como la cadena de prototipos, y explica por qué objetos diferentes pueden tener disponibles propiedades y métodos definidos en otros objetos.

+ +

Bien, para ser exactos, los métodos y propiedades son definidos en la propiedad prototype, que reside en la función constructora del objeto, no en la instancia misma del objeto.

+ +

En JavaScript, se establece un enlace entre la instancia del objeto y su prototipo (su propiedad __proto__, la cual es derivada de la propiedad prototype sobre el constructor), y las propiedades y metodos son encontrados recorriendo la cadena de prototipos.

+ +

Nota: Es importante entender que, tanto el prototipo de la instancia de un objeto (al cual se accede mediante Object.getPrototypeOf(obj), o a través de la propiedad __proto__) como el prototipo que contiene el constructor (que se encuentra en la propiedad prototype del constructor) hacen referencia al mismo objeto.

+ +

Vamos a echar un vistazo a algunos ejemplos para intentar aclarar estos conceptos.

+ +

Entendiendo objectos prototipos

+ +

Volvamos al ejemplo anterior en el que acabamos definiendo nuestro constructor Person() — cargue el ejemplo en su navegador. Si aún no lo tienes luego de haber trabajado el último artículo, usa nuestro ejemplo oojs-class-further-exercises.html (vea también el código fuente).

+ +

En este ejemplo, hemos definido una función constructor, así:

+ +
function Persona(nombre, apellido, edad, genero, intereses) {
+
+  // definiendo de propiedades y métodos
+  this.first = first;
+  this.last = last;
+//...
+}
+
+ +

Entonces hemos creado una instancia de un objeto como este:

+ +
var person1 = new Persona('Bob', 'Smith', 32, 'hombre', ['music', 'skiing']);
+ +

Si escribe "person1." en su consola JavaScript, debería ver que el navegador intenta completarlo automáticamente con los nombres de miembro disponibles en este objeto:

+ +

+ +

En esta lista, podra ver los miembros definidos en el objeto prototipo de person1, que es la Persona() (Persona() es el constructor) - nombre, edad, género, intereses, biografía y saludos. Sin embargo, también verá algunos otros miembros - watch, valueOf, etc - que están definidos en el objeto prototipo de Persona() 's, que es un Objeto (Object). Esto demuestra que el prototipo cadena funciona.

+ +

+ +

Entonces, ¿qué sucede si llama a un método en person1, que está definido en Object? Por ejemplo:

+ +
person1.valueOf()
+ +

Este método valueOf() simplemente retornará el valor del objeto sobre el que se llama - ¡pruébalo y verás! En este caso, lo que pasa es que:

+ + + +
+

Nota: Queremos reiterar que los métodos y propiedades no se copian de un objeto a otro en la cadena del prototipo. Ellos son accedidos subiendo por la cadena como se ha descrito anteriormente.

+
+ +
+

Nota: No existe oficialmente una forma de acceder directamente al objeto prototipo de un objeto - los "enlaces" entre los elementos de la cadena están definidos en una propiedad interna, denominada [[prototipo]] en la especificación del lenguaje JavaScript (ver {{glossary("ECMAScript")}}).

+ +

La mayoría de los navegadores modernos, sin embargo, ofrecen una propiedad disponible llamada __proto__ (es decir, 2 subrayados en cada lado), que contiene el objeto prototipo del constructor del objeto. Por ejemplo, pruebe person1.__proto__ y person1.__proto__.__proto__ para ver cómo se ve la cadena en código!

+ +

Desde ECMAScript 2015 se puede acceder indirectamente al objeto prototipo de un objeto mediante Object.getPrototypeOf(obj).

+
+ +

La propiedad prototype: Donde se definen los miembros hereditarios

+ +

Entonces, ¿dónde se definen las propiedades y métodos heredados? Si miras la página de referencia de Object, verás en la parte izquierda un gran número de propiedades y métodos - muchos más que el número de miembros heredados que vimos disponibles en el objeto person1. Algunos son heredados y otros no, ¿por qué?

+ +

La respuesta es que los heredados son los que están definidos en la propiedad prototype (podría llamarse subespacio de nombres), es decir, los que empiezan con Object.prototype, y no los que empiezan sólo con Object. El valor de la propiedad del prototipo es un objeto, que es básicamente un repositorio(bucket) para almacenar propiedades y métodos que queremos que sean heredados por los objetos más abajo en la cadena del prototipo.

+ +

Así que Object.prototype.watch(), Object.prototype.valueOf(), etc., están disponibles para cualquier tipo de objeto que herede de Object.prototype, incluyendo nuevas instancias de objeto creadas desde el constructor.

+ +

Object.is(), Object.keys(), y otros miembros no definidos dentro del prototipo del repositorio(bucket) no son heredados por instancias de objeto o tipos de objeto que heredan de Object.prototype. Sino que son métodos/propiedades disponibles sólo en el propio constructor Object().

+ +
+

Nota: Esto parece extraño - ¿cómo se puede tener un método definido en un constructor, que en sí mismo es una función? Bueno, una función es también un tipo de objeto - vea la referencia del constructor de Function() si no nos cree.

+
+ +
    +
  1. Puede comprobar las propiedades de los prototipos existentes - vuelva a nuestro ejemplo anterior e intente introducir lo siguiente en la consola JavaScript: +
    Person.prototype
    +
  2. +
  3. El resultado no le mostrará mucho - después de todo, no hemos definido nada en el prototipo de nuestro constructor personalizado! Por defecto, el prototipo de un constructor siempre comienza vacío. Ahora intente lo siguiente: +
    Object.prototype
    +
  4. +
+ +

Verá un gran número de métodos definidos en la propiedad Prototype de Object, que están disponibles en los objetos que heredan de Object, como se ha mostrado anteriormente.

+ +

Verá otros ejemplos de herencia de cadena de prototipos en todo JavaScript - intente buscar los métodos y propiedades definidas en el prototipo de los objetos globales String, Date, Number y Array, por ejemplo. Todos ellos tienen un número de miembros definidos en su prototipo, por lo que, por ejemplo, cuando se crea una cadena, como ésta:

+ +
var myString = 'Esto es mi String.';
+ +

myString inmediatamente tiene una serie de métodos útiles disponibles en él, como split(), indexOf(), replace(), etc.

+ +
+

Importante: La propiedad prototype es una de las partes más confusamente nombradas de JavaScript - podría pensarse que this apunta al objeto prototipo del objeto actual, pero no lo hace (es un objeto interno al que puede accederse mediante __proto__, ¿recuerda?). en su lugar, prototype es una propiedad que contiene un objeto en el que se definen los miembros que se desea que se hereden.

+
+ +

Revisando create()

+ +

Anteriormente mostramos cómo Object.create() crea una nueva instancia de objeto.

+ +
    +
  1. Por ejemplo, pruebe esto en la consola JavaScript de su ejemplo anterior: +
    var person2 = Object.create(person1);
    +
  2. +
  3. Lo que hace create() es crear un nuevo objeto a partir de un objeto prototipo específico. Aquí, la person2 se crea utilizando la person1 como objeto prototipo. Puede comprobarlo introduciendo lo siguiente en la consola: +
    person2.__proto__
    +
  4. +
+ +

Esto devolverá el objeto Persona.

+ +

La propiedad constructor

+ +

Cada función de constructor tiene una propiedad prototype cuyo valor es un objeto que contiene una propiedad constructor. Esta propiedad constructor apunta a la función constructor original.

+ +

Como verá en la siguiente sección, las propiedades definidas en la propiedad Person.prototype (o en general en la propiedad prototype de una función de constructor, que es un objeto, como se mencionó en la sección anterior) se hacen disponibles a todas las instancias de objetos creadas utilizando el constructor Person(). Por lo tanto, la propiedad del constructor también está disponible tanto para los objetos person1 como para los objetos person2.

+ +
    +
  1. Por ejemplo, pruebe estos comandos en la consola: +
    person1.constructor
    +person2.constructor
    + +

    Ambos deberían devolver el constructor Person(), ya que contienen la definición original de esas instancias.

    + +

    Un truco interesante es que se puede añadir paréntesis al final de la propiedad constructor (añadiendo todos los parámetros requeridos) para crear otra instancia desde ese constructor. Después de todo, el constructor es una función, por lo que puede ser invocada usando paréntesis; solamente se necesita incluir la palabra clave new para especificar que se quiere usar la función como un constructor.

    +
  2. +
  3. Inténtese esto en la consola: +
    let person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);
    +
  4. +
  5. Ahora intente acceder a las características del nuevo objeto, como: +
    person3.name.first
    +person3.age
    +person3.bio()
    +
  6. +
+ +

Esto funciona. No se necesita usarlo con frecuencia, pero puede ser realmente útil cuando se quiera crear una instancia nueva y por alguna razón no se tenga disponible fácilmente una referencia al constructor original.

+ +

La propiedad constructor tiene otros usos. Por ejemplo, si se tiene una instancia y se quiere devolver el nombre del que el constructor es una instancia, se puede usar lo siguiente:

+ +
instanceName.constructor.name
+ +

Intente esto, por ejemplo:

+ +
person1.constructor.name
+
+ +
+

Nota: El valor de constructor.name puede cambiar (debido a herencia de prototipos, binding, preprocesores, transpiladores, etc.), por lo que para ejemplos más complejos es preferible usar el operador instanceof en su lugar. 

+
+ +
    +
+ +

Modificando prototipos

+ +

Vamos a echar un vistzo a un ejemplo para modificar la propiedad prototype de una función constructor (los métodos añadidos a la propiedad prototipo están disponibles en todas las instancias de los objetos creados a partir del constructor).

+ +
    +
  1. Regresemos a nuestro ejemplo oojs-class-further-exercises.html y creemos una copia local del código fuente. Debajo del código JavaScript existente, agrega el siguiente código, el cuál añade un nuevo método a la propiedad prototype del constructor: + +
    Person.prototype.farewell = function() {
    +  alert(this.name.first + ' has left the building. Bye for now!');
    +};
    +
  2. +
  3. Guarda el código y abre la página en el navegador, e ingresa lo siguiente en la entrada de texto. +
    person1.farewell();
    +
  4. +
+ +

Deberías obtener un mensaje de alerta mostrando el nombre de la persona como se define dentro del constructor. Esto es realmente útil, pero lo que es más útil es que toda la cadena de herencia se ha actualizado dinámicamente; automáticamente hace que este nuevo método esté disponible en todas las instancias del objeto creadas desde el constructor

+ +

Piensa sobre esto por un momento. En nuestro código definimos el constructor, luego creamos una insancia del objeto desde el constructor, después agregamos un nuevo método a el prototipo del constructor.

+ +
function Person(first, last, age, gender, interests) {
+
+  // property and method definitions
+
+}
+
+var person1 = new Person('Tammi', 'Smith', 32, 'neutral', ['music', 'skiing', 'kickboxing']);
+
+Person.prototype.farewell = function() {
+  alert(this.name.first + ' has left the building. Bye for now!');
+};.
+ +

Pero el método farewell() aún se encuentra disponible en la instancia person1, su funcionalidad disponible ha sido automáticamente actualizada incluído en método recién definido farewell().

+ +
+

Nota: Si estás teniendo problemas haciendo funcionar este ejemplo, echa un vistazo en nuestro ejemplo oojs-class-prototype.html (míralo ejecutarse en tiempo real).

+
+ +

Raramente verás propiedades definidas en la propiedad prototype, ya no son muy flexibles cuando son definidas de esta forma. Por ejemplo, puedes añadir una propiedad como esta:

+ +
Person.prototype.fullName = 'Bob Smith';
+
+ +

Esto no es muy flexible, ya que la persona podría no llamarse así. Sería mucho mejor construir fullname desde name.first y name.last.

+ +
Person.prototype.fullName = this.name.first + ' ' + this.name.last;
+
+ +

Sin embargo esto no funciona, ya que this estará referenciando al scope global en este caso, no al scope de la función. Llamar esta propiedad retornaría undefined undefined. Esto funcionó bien en el método que declaramos anteriormente dentro del prototipo, porque se encuentra dentro del scope de la función, que se transferirá con éxito al scope de la instancia del objeto.Así que deberías definir propiedades constantes en el prototipo (p.e. una que nunca necesite cambiar), pero generalmente funciona mejor definir propiedades dentro del constructor.

+ +

De hecho, un patrón bastante común para la mayoría de definiciones de objetos es declarar las propiedades dentro del constructor, y los métodos en el prototipo. Esto hace el código más fácil de leer, ya que el constructor sólo contiene las definiciones de propiedades, y los métodos están en bloques separados. Por ejemplo:

+ +
// Constructor with property definitions
+
+function Test(a, b, c, d) {
+  // property definitions
+}
+
+// First method definition
+
+Test.prototype.x = function() { ... };
+
+// Second method definition
+
+Test.prototype.y = function() { ... };
+
+// etc.
+
+ +

Este patrón puede verse en acción en el ejemplo de la aplicación de planificador escolar de Piotr Zalewa.

+ +

Resumen

+ +

Este articulo ha cubierto prototipos de objeto JavaScript, incluyendo como las cadenas de objeto prototipo permiten a los objetos heredar caracteristicas de una a otra, la propiedad prototipo y como puede ser usado para agregar metodos a los constructores, y otros temas relacionados.

+ +

En el proximos articulo vamos a ver como puedes implementar la herencia de funcionalidades entre dos de tus propios objetos personalizados.

+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}

+ +

In this module

+ + -- cgit v1.2.3-54-g00ecf