diff options
Diffstat (limited to 'files/es/learn/javascript/objects')
8 files changed, 2160 insertions, 0 deletions
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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar esta evaluación, debería haber revisado todos los artículos de este módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para probar la comprensión de objetos JavaScript y construcciones orientadas a objetos.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para iniciar esta evaluación, haz una copia local de <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html">index-finished.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a>, y <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">main-finished.js</a> de nuestro último artículo en un nuevo directorio en tu ordenador.</p> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, puede usar un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> 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 <code><script></code>/<code><style></code> dentro de la página.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>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 <code>Shape()</code> 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.</p> + +<p>La siguiente captura de pantalla te da una idea de cómo debería verse el programa final.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13875/bouncing-evil-circle.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>Para darle una idea eche un vistazo al <a href="http://mdn.github.io/learning-area/javascript/oojs/assessment/">ejemplo final</a> (¡no mire el código fuente!)</p> + +<h2 id="Pasos_para_completar">Pasos para completar</h2> + +<p>Las siguientes secciones describen lo que debe hacer.</p> + +<h3 id="Creando_nuestro_nuevos_objetos">Creando nuestro nuevos objetos</h3> + +<p>Primero de todo, cambia la constructora existente de <code>Ball()</code> para que se convierta en un constructor <code>Shape()</code> y añade un nuevo constructor <code>Ball()</code>:</p> + +<ol> + <li>El constructor <code>Shape()</code> debe definir las propiedades <code>x</code>, <code>y</code>, <code>velX</code>, y <code>velY</code> del mismo modo que lo hacía el constructor <code>Ball()</code> constructor original, pero no las propiedades <code>color</code> y <code>size</code>.</li> + <li>También debe definir una nueva propiedad <code>exists</code>, 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 (<code>true</code>/<code>false</code>).</li> + <li>El constructor <code>Ball()</code> debe heredar las propiedades <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, y <code>exists</code> del constructor <code>Shape()</code>.</li> + <li>También debe definir propiedades <code>color</code> y <code>size</code>, como el constructor original <code>Ball()</code> hacía.</li> + <li>Recuerda configurar el <code>prototype </code>del constructor <code>Ball()</code> correctamente.</li> +</ol> + +<p>Los métodos de la pelota <code>draw()</code>, <code>update()</code>, y <code>collisionDetect()</code> deben ser capaces de permanecer exactamente igual que antes.</p> + +<p>También necesitas añadir un parámetro nuevo a la llamada del constructor <code>new Ball() ( ... )</code> — El parámetro <code>exists</code> debe ser el quinto parámetro y debe tener un valor <code>true</code>.</p> + +<p>En este punto, intente volver a cargar el código; debería funcionar igual que antes, con nuestros objetos rediseñados.</p> + +<h3 id="Definiendo_EvilCircle">Definiendo EvilCircle()</h3> + +<p>Ahora es el momento de conocer al chico malo: ¡el <code>EvilCircle()</code>! Nuestro juego solo involucrará un círculo malvado, pero lo vamos a seguir definiendo usando un constructor que hereda de <code>Shape()</code> 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.</p> + +<p>El constructor <code>EvilCircle()</code> debe heredar <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, y <code>exists</code> from <code>Shape()</code>, pero <code>velX</code> y <code>velY</code> debe ser igual a 20.</p> + +<p>Debería hacer algo como <code>Shape.call(this, x, y, 20, 20, exists);</code></p> + +<p>Debe definir también sus propias propiedades, como las siguientes:</p> + +<ul> + <li><code>color</code> — <code>'white'</code></li> + <li><code>size</code> — <code>10</code></li> +</ul> + +<p>Otra vez, recuerda definir tus propiedades heredadas como parámetros en el constructor, y configura las propiedades <code>prototype</code> y <code>constructor</code> properties correc.tamente</p> + +<h3 id="Definiendo_los_métodos_de_EvilCircle">Definiendo los métodos de EvilCircle()</h3> + +<p><code>EvilCircle()</code> debe tener cuatro métodos como se desciben a continuación.</p> + +<h4 id="draw"><code>draw()</code></h4> + +<p>Este método tiene el mismo propósito que el método <code>draw()</code>de <code>Ball()</code>: 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 <code>Ball.prototype.draw</code>. Luego deberías hacer los siguientes cambios.:</p> + +<ul> + <li>Queremos que el círculo del mal no se complete, sino que simplemente tenga una línea exterior (trazo). Puedes lograr esto actualizando <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> y <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> a <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle">strokeStyle</a></code> y <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/stroke">stroke()</a></code>.</li> + <li>También queremos que el trazo sea un poco más grueso, para que puedas ver el círculo malvado con mayor facilidad. Podemos lograr esto configurando un valor para <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth">lineWidth</a></code> en algún lugar después de la llamada <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> (3 hará).</li> +</ul> + +<h4 id="checkBounds"><code>checkBounds()</code></h4> + +<p>Este método hara lo mismo que la primera parte de la función <code>update()</code> de <code>Ball()</code> — 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 <code>Ball.prototype.update</code>, hay algunos cambios que debe hacer:</p> + +<ul> + <li>Deshazte de las dos últimas líneas: no queremos actualizar automáticamente la posición del círculo maligno en cada cuadro, porque lo moveremos de alguna otra manera, como verás a continuación.</li> + <li>Dentro de las declaraciones <code>if()</code>, si el test devuelve true no queremos actualizar <code>velX</code>/<code>velY</code>; queremos cambiar el valor de <code>x</code>/<code>y</code> por lo que el círculo del mal se rebota en la pantalla ligeramente. Agregar o restar (según corresponda) la propiedad de tamaño del círculo maligno (<code>size</code>) tendría sentido.</li> +</ul> + +<h4 id="setControls"><code>setControls()</code></h4> + +<p>Este método agregará un detector de eventos <code>onkeydown</code> al objeto <code>window</code> 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:</p> + +<pre class="brush: js notranslate">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; + } + }</pre> + +<p>Por tanto cuando se presiona una tecla, el evento del objeto <a href="/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> 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.</p> + +<ul> + <li>Para obtener un punto de bonificación, avísenos a qué teclas se asignan los códigos de clave especificados.</li> + <li>Para otro punto de bonificación, ¿nos podrías decir por qué tenemos que configurar <code>var _this = this;</code> en la posición en la que está? Es algo que se hace en la función scope.</li> +</ul> + +<h4 id="collisionDetect"><code>collisionDetect()</code></h4> + +<p>Este método actuará de una forma muy similar al método <code>collisionDetect() </code>de <code>Ball()</code>, así que puede usar una copia de eso como una base para el nuevo método. Pero hay algunas diferencias:</p> + +<ul> + <li>En el exterior de la declaración <code>if</code>, ya no es necesario comprobar si la bola actual en la iteración es la misma que la bola que está haciendo la comprobación, porque ya no es una bola, ¡es el círculo del mal! En su lugar, debe hacer una prueba para ver si existe la bola que se está verificando (¿con qué propiedad podría hacerlo?). Si no existe, ya ha sido devorado por el círculo maligno, por lo que no es necesario volver a comprobarlo.</li> + <li>En el interior de la declaración <code>if</code>, ya no desea que los objetos cambien de color cuando se detecta una colisión; en cambio, desea que no existan más bolas que colisionen con el círculo maligno (una vez más, ¿cómo cree que haría eso?).</li> +</ul> + +<h3 id="Trayendo_el_círculo_del_mal_al_programa.">Trayendo el círculo del mal al programa.</h3> + +<p>Ahora que hemos definido el círculo maligno, debemos hacerlo aparecer en nuestra escena. Para hacerlo, necesitas hacer alguno cambios a la función <code>loop()</code>.</p> + +<ul> + <li>Primero de todo, crea una nueva instancia del círculo maligno (especifica los parámetros necesarios ), entonces llama al método <code>setControls()</code> . Solo necesita hacer estas dos cosas una vez, no en cada iteración del bucle.</li> + <li>En el punto en el que intera por todas las pelotas y llama a las funciones <code>draw()</code>, <code>update()</code>, y<code>collisionDetect()</code> para cada una, hazlo para que estas funciones solo sean llamadas si la bola actual existe.</li> + <li>Llama a los métodos de la instancia de la pelota maligna <code>draw()</code>, <code>checkBounds()</code>, y<code>collisionDetect()</code> en cada iteración del bucle.</li> +</ul> + +<h3 id="Implementando_el_contador_de_puntuación.">Implementando el contador de puntuación.</h3> + +<p>Para implementar el contador de puntuación sigue estos pasos:</p> + +<ol> + <li>En tu archivo HTML añade un elemento {{HTMLElement("p")}} justo debajo del elemento {{HTMLElement("h1")}} que contiene el texto "Ball count: ".</li> + <li>En tu archivo CSS, agregue la siguiente regla en la parte inferior: + <pre class="brush: css notranslate">p { + position: absolute; + margin: 0; + top: 35px; + right: 5px; + color: #aaa; +}</pre> + </li> + <li>En su JavaScript, realice las siguientes actualizaciones: + <ul> + <li>Cree una variable que almacene una referencia al párrafo.</li> + <li>Mantenga un recuento de la cantidad de bolas en la pantalla de alguna manera.</li> + <li>Incrementa el conteo y muestra el número actualizado de bolas cada vez que se agrega una bola a la escena.</li> + <li>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).</li> + </ul> + </li> +</ol> + +<h2 id="Consejos">Consejos</h2> + +<ul> + <li>Esta evaluación es bastante desafiante. Da cada paso despacio y con cuidado.</li> + <li>Puede ser una idea mantener una copia separada de la demostración después de que cada etapa esté funcionando, para que pueda consultarla si se encuentra en problemas más adelante.</li> +</ul> + +<h2 id="Evaluación">Evaluación</h2> + +<p>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 <a href="https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689">discussion thread for this exercise</a>, o en el <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC channel en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Prueba a hacer el ejercicio primero — no hay nada que ganar con trampa!</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> 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 +--- +<div><font><font>{{LearnSidebar}}</font></font></div> + +<div>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</div> + +<p class="summary"><font><font>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.</font></font></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row"><font><font>Prerrequisitos:</font></font></th> + <td><font><font>Conocimientos básicos de informática, conocimientos básicos de HTML y CSS, familiaridad con los principios básicos de JavaScript (consulta </font></font><a href="/es/docs/Learn/JavaScript/First_steps"><font><font>Primeros pasos</font></font></a><font><font> y </font></font><a href="/es/docs/Learn/JavaScript/Building_blocks"><font><font>Bloques de construcción</font></font></a><font><font>).</font></font></td> + </tr> + <tr> + <th scope="row"><font><font>Objetivo:</font></font></th> + <td><font><font>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.</font></font></td> + </tr> + </tbody> +</table> + +<h2 id="Conceptos_básicos_de_objeto"><font><font>Conceptos básicos de objeto</font></font></h2> + +<p><font><font>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.</font></font></p> + +<p><font><font>Para empezar, haz una copia local de nuestro </font><font>archivo </font></font><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html"><font><font>oojs.html</font></font></a><font><font> . </font><font>Esto contiene muy poco: un elemento {{HTMLElement ("script")}} para que escribas tu código fuente en él. Lo </font><font>usaremos como base para explorar la sintaxis básica de los objetos.</font></font></p> + +<p><font><font>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. </font><font>Intenta ingresar lo siguiente debajo del código JavaScript que ya está en tu archivo, luego guarda y actualiza:</font></font></p> + +<pre class="brush: js notranslate"><font><font>var persona = {};</font></font></pre> + +<p><font><font>Si ingresas </font></font><code>persona</code><font><font> en tu entrada de texto y presionas el botón, debes obtener el siguiente resultado:</font></font></p> + +<pre class="brush: js notranslate"><font><font>[objeto Objeto]</font></font></pre> + +<p><font><font>¡Felicidades!, acabas de crear tu primer objeto. </font><font>¡Trabajo realizado! </font><font>Pero este es un objeto vacío, por lo que realmente no podemos hacer mucho con él. </font><font>Actualicemos nuestro objeto para que se vea así:</font></font></p> + +<pre class="brush: js notranslate"><font><font>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] + '. '); + } +};</font></font> +</pre> + +<p><font><font>Después de guardar y actualizar, intenta ingresar algunos de los siguientes en tu entrada de texto:</font></font></p> + +<pre class="brush: js notranslate"><font><font>persona.nombre +persona.nombre[0] +persona.edad +persona.intereses[1]</font></font><font><font> +persona.bio() +persona.saludo()</font></font></pre> + +<p><font><font>¡Ahora tienes algunos datos y funcionalidades dentro de tu objeto, y ahora puedes acceder a ellos con una sintaxis simple y agradable!</font></font></p> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes problemas para hacer que esto funcione, intenta comparar tu código con nuestra versión - ve <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html">oojs-finished.html</a> (también <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html">ve que se ejecuta en vivo</a>). 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.</p> +</div> + +<p>Entonces, ¿qué está pasando aquí? Bien, un objeto se compone de varios miembros, cada uno de los cuales tiene un nombre (por ejemplo, <code>nombre</code> y <code>edad</code>) y un valor (por ejemplo, <code>['Bob', 'Smith']</code> y <code>32</code>). 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:</p> + +<pre class="brush: js notranslate">var nombreObjeto = { + miembro1Nombre: miembro1Valor, + miembro2Nombre: miembro2Valor, + miembro3Nombre: miembro3Valor +}</pre> + +<p>El valor de un miembro de un objeto puede ser prácticamente cualquier cosa: en nuestro objeto <code>persona </code>tenemos una cadena de texto, un número, dos arreglos y dos funciones. Los primeros cuatro elementos son elementos de datos y se denominan <strong>propiedades</strong> del objeto. Los dos últimos elementos son funciones que le permiten al objeto hacer algo con esos datos, y se les denomina <strong>métodos</strong> del objeto.</p> + +<p>Un objeto como este se conoce como un <strong>objeto literal </strong>— 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.</p> + +<p>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.</p> + +<h2 id="Notación_de_punto">Notación de punto</h2> + +<p>Arriba, accediste a las propiedades y métodos del objeto usando <strong>notación de punto (dot notation)</strong>. El nombre del objeto (<code>persona</code>) actúa como el <strong>espacio de nombre (namespace)</strong>; al cual se debe ingresar primero para acceder a cualquier elemento <strong>encapsulado</strong> 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:</p> + +<pre class="brush: js notranslate">persona.edad +persona.<font><font>intereses</font></font>[1] +persona.bio()</pre> + +<h3 id="Espacios_de_nombres_secundarios">Espacios de nombres secundarios</h3> + +<p>Incluso es posible hacer que el valor de un miembro del objeto sea otro objeto. Por ejemplo, intenta cambiar el miembro nombre de</p> + +<pre class="brush: js notranslate">nombre: ['Bob', 'Smith'],</pre> + +<p>a</p> + +<pre class="brush: js notranslate">nombre : { + pila: 'Bob', + apellido: 'Smith' +},</pre> + +<p>Aquí estamos creando efectivamente un <strong>espacio de nombre secundario (sub-namespace)</strong>. 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:</p> + +<pre class="brush: js notranslate">persona.nombre.pila +persona.nombre.apellido</pre> + +<p><strong>Importante</strong>: en este punto, también deberás revisar tu código y cambiar cualquier instancia de</p> + +<pre class="brush: js notranslate">nombre[0] +nombre[1]</pre> + +<p>a</p> + +<pre class="brush: js notranslate">nombre.pila +nombre.apellido</pre> + +<p>De lo contrario, sus métodos ya no funcionarán.</p> + +<h2 id="Notación_de_corchetes">Notación de corchetes</h2> + +<p>Hay otra manera de acceder a las propiedades del objeto, usando la notación de corchetes. En lugar de usar estos:</p> + +<pre class="brush: js notranslate">persona.edad +persona.nombre.pila</pre> + +<p>Puedes usar</p> + +<pre class="brush: js notranslate">persona['edad'] +persona['nombre']['pila']</pre> + +<p>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 <strong>arreglos asociativos</strong>: asocian cadenas de texto a valores de la misma manera que las arreglos asocian números a valores.</p> + +<h2 id="Establecer_miembros_de_objetos">Establecer miembros de objetos</h2> + +<p>Hasta ahora solo hemos buscado recuperar (u <strong>obtener</strong>) miembros del objeto: también puede <strong>establecer</strong> (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:</p> + +<pre class="brush: js notranslate">persona.edad = 45; +persona['nombre']['apellido'] = 'Cratchit';</pre> + +<p>Intenta ingresar estas líneas y luego vuelve a ver a los miembros para ver cómo han cambiado:</p> + +<pre class="brush: js notranslate">persona.edad +persona['nombre']['apellido']</pre> + +<p>Establecer miembros no solo es actualizar los valores de las propiedades y métodos existentes; también puedes crear miembros completamente nuevos. Prueba estos:</p> + +<pre class="brush: js notranslate">persona['ojos'] = 'avellana'; +persona.despedida = function() { alert("¡Adiós a todos!"); }</pre> + +<p>Ahora puedes probar a los nuevos miembros:</p> + +<pre class="brush: js notranslate">persona['ojos'] +person.despedida()</pre> + +<p>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:</p> + +<pre class="brush: js notranslate">var nombrePerzonalizado = entradaNombre.value; +var valorPerzonalizado = entradaValor.value;</pre> + +<p>entonces podríamos agregar este nuevo miembro nombre y valor al objeto <code>persona</code> de esta manera:</p> + +<pre class="brush: js notranslate">persona[nombrePerzonalizado] = valorPerzonalizado;</pre> + +<p>Para probar esto, intenta agregar las siguientes líneas en tu código, justo debajo de la llave de cierre del objeto <code>persona</code>:</p> + +<pre class="brush: js notranslate">var nombrePerzonalizado = 'altura'; +var valorPerzonalizado = '1.75m'; +persona[nombrePerzonalizado] = valorPerzonalizado;</pre> + +<p>Ahora intenta guardar y actualizar, e ingresa lo siguiente en tu entrada de texto:</p> + +<pre class="brush: js notranslate">persona.altura</pre> + +<p>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.</p> + +<h2 id="¿Qué_es_this_este">¿Qué es "this" (este)?</h2> + +<p>Es posible que hayas notado algo un poco extraño en nuestros métodos. Mira esto, por ejemplo:</p> + +<pre class="brush: js notranslate"><font><font>saludo</font></font>: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre.pila + '.'); +}</pre> + +<p>Probablemente te estés preguntando qué es <code>"this"</code>. La palabra clave <code>this</code> se refiere al objeto actual en el que se está escribiendo el código, por lo que en este caso <code>this</code> es equivalente a la <code>persona</code>. Entonces, ¿por qué no escribir <code>persona</code> en su lugar? Como verás en el artículo <a href="/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientado a objetos para principiantes</a> cuando comenzaremos a crear constructores, etc., <code>this</code> 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 <code>persona</code>) pueden tener diferentes nombres, pero querráx usar su propio nombre al decir su saludo).</p> + +<p>Vamos a ilustrar lo que queremos decir con un par de objetos persona simplificados:</p> + +<pre class="brush: js notranslate">var persona1 = { + nombre: 'Chris', + saludo: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre + '.'); + } +} + +var persona2 = { + nombre: 'Brian', + saludo: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre + '.'); + } +}</pre> + +<p>En este caso, <code>persona1.saludo()</code> mostrará "<font><font>¡Hola!</font></font>, Soy Chris"; <code>persona2.saludo()</code> por otro lado mostrará "<font><font>¡Hola!</font></font>, Soy Brian", aunque el código del método es exactamente el mismo en cada caso. Como dijimos antes, <code>this</code> 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.</p> + +<h2 id="Has_estado_usando_objetos_todo_el_tiempo">Has estado usando objetos todo el tiempo</h2> + +<p>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.</p> + +<p>Entonces cuando usaste métodos de cadenas de texto como:</p> + +<pre class="brush: js notranslate">myCadena.split(',');</pre> + +<p>Estabas usando un método disponible en una instancia de la clase <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>. 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.</p> + +<p>Cuando accediste al modelo de objetos del documento (document object model) usando líneas como esta:</p> + +<pre class="brush: js notranslate">var miDiv = document.createElement('div'); +var miVideo = document.querySelector('video');</pre> + +<p>Estaba usando métodos disponibles en una instancia de la clase <code><a href="/es/docs/Web/API/Document">Document</a></code>. Para cada página web cargada, se crea una instancia de <code>Document</code>, llamada <code>document</code>, 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.</p> + +<p>Lo mismo puede decirse de prácticamente cualquier otro Objeto/API incorporado que hayad estado utilizando: <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>, <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Math">Math</a></code>, etc.</p> + +<p>Ten en cuenta que los Objetos/API incorporados no siempre crean instancias de objetos automáticamente. Como ejemplo, la <a href="/es/docs/Web/API/Notifications_API">API de Notificaciones</a>, 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:</p> + +<pre class="brush: js notranslate">var miNotificacion = new Notification('¡Hola!');</pre> + +<p>De nuevo, veremos qué son los constructores en un artículo posterior.</p> + +<div class="note"> +<p><strong>Nota</strong>: Es útil pensar en la forma en que los objetos se comunican como <strong>paso de mensajes</strong> — 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.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p><font><font>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. </font><font>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 </font></font><font><font>objeto </font></font><code>persona</code><font><font> 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. </font><font>Los objetos nos permiten mantener la información segura y protegida en su propio paquete, fuera del peligro.</font></font></p> + +<p><font><font>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.</font></font></p> + +<p>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</p> diff --git a/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_de_objetos/index.html b/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_de_objetos/index.html new file mode 100644 index 0000000000..6dfaaf0d08 --- /dev/null +++ b/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Conocimientos básicos de computadores. Entendimiento básico de HTML y CSS. Familiaridad con los conceptos básicos de JavaScript (vea <a href="/es/docs/Learn/JavaScript/First_steps">Primeros Pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Elementos básicos de JavaScript</a>) y OOJS (vea <a href="/es/docs/Learn/JavaScript/Objects/Basics">Conceptos básicos de los objetos JavaScript</a>).</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Ganar experiencia en el uso de objetos y el uso de programación orientada a objetos en un contexto realista.</td> + </tr> + </tbody> +</table> + +<h2 id="Lanzemos_algunas_pelotas">Lanzemos algunas pelotas</h2> + +<p>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:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13865/bouncing-balls.png" style="display: block; height: 614px; margin: 0px auto; width: 800px;"></p> + +<ol> +</ol> + +<p>En este ejemplo se utilizará <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Canvas API</a> para dibujar las pelotas en la pantalla y la API <a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> 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 <strong>detección de colisiones</strong>). </p> + +<h2 id="Primeros_pasos">Primeros pasos</h2> + +<p>Para comenzar haga una copia en su computador de los archivos: <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a></code>, y <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js">main.js</a></code>. Estos contienen:</p> + +<ol> + <li>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. </li> + <li>Algunos estilos sencillos que servirán para ubicar el elemento <code><h1></code>, ocultar la barra de desplazamiento y los margenes del borde de la página (para que luzca mejor).</li> + <li>Un archivo JavaScript que sirve para definir el elemento <code><canvas></code> y las funciones que vamos a usar.</li> +</ol> + +<p>La primera parte del script es:</p> + +<pre class="brush: js">var canvas = document.querySelector('canvas'); + +var ctx = canvas.getContext('2d'); + +var width = canvas.width = window.innerWidth; +var height = canvas.height = window.innerHeight;</pre> + +<p>Este script obtiene una referencia del elemento <code><canvas></code>, luego llama al método <code><a href="/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext()</a></code> para definir un contexto en el cual se pueda comenzar a dibujar. La resultado de la variable (<code>ctx</code>) es el objeto que representa directamente el área de dibujo del <code><canvas></code> y permite dibujar elementos 2D en él. </p> + +<p>A continuación se da valor a las variables <code>width</code> and <code>height</code> que corresponden al ancho y alto del elemento <em>canvas</em> (representado por las propiedades <code>canvas.width</code> y <code>canvas.height</code>), de manera que el alto y ancho coincidan con el alto y ancho del navegador (<em>viewport</em>) cuyos valores se obtienen directamente de las propiedades <em>window.innerWidth </em>y <em>window.innerHeight</em>.</p> + +<p>Puede ver que en el código se encadenan varias asignaciones, para obtener valores más rápidamente. Esto se puede hacer.</p> + +<p>La última parte del script, es la siguiente:</p> + +<pre class="brush: js">function random(min, max) { + var num = Math.floor(Math.random() * (max - min + 1)) + min; + return num; +}</pre> + +<p>Esta función recibe dos números como argumentos de entrada (valor mínimo y maximo) y devuelve un número aleatorio entre ellos.</p> + +<h2 id="Modelando_una_pelota_en_nuestro_programa">Modelando una pelota en nuestro programa</h2> + +<p>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 (<em>Ball</em>), en nuestro código.</p> + +<pre class="brush: js">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 +}</pre> + +<p>Aquí incluimos algunos parámetros que serán las propiedades que cada pelota necesita para funcionar en nuestro programa: </p> + +<ul> + <li>las coordenadas <code>x</code> e <code>y</code>— correspondientes a la posición horizontal y vertical de la pelota. Estas pueden variar entre un valor 0 (el la esquina superior izquierda) hasta el valor del ancho y alto del navegador ( esquina inferior derecha).</li> + <li>velocidad horizontal y vertical (<code>velX</code> y <code>velY</code>) — cada pelota tiene una velocidad vertical y horizontal; en la parte práctica, estos valores se añadirán a las coordenadas x e y cuando animemos el movimiento de las pelotas, así en cada incremento de visualización de <em>frame</em>, se desplazarán esta cantidad.</li> + <li><code>color</code> — cada pelota posee un color.</li> + <li><code>size</code> — cada pelota tiene un tamaño, este será su radio en pixels.</li> +</ul> + +<p>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. </p> + +<h3 id="Dibujando_las_pelotas">Dibujando las pelotas</h3> + +<p>Para dibujar, añadiremos el siguiente método <code>draw()</code> al prototipo del objeto <code>Ball():</code></p> + +<pre class="brush: js">Ball.prototype.draw = function() { + ctx.beginPath(); + ctx.fillStyle = this.color; + ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<p>Con esta función cada objeto pelota <code>Ball()</code> puede dibujarse en la pantalla utilizando el contexto 2D definido anteriormente (<code>ctx</code>) </p> + +<ul> + <li>Primero usamos <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> para declarar que empezaremos a dibujar una forma en el <em>canvas</em>.</li> + <li>A continuación usamos el <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> para definir el color de la forma. Haremos que coincida con la propiedad <code>color.</code></li> + <li>A continuación con el método <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/arc">arc()</a></code> se traza un arco. Sus parámetros son: + <ul> + <li>La posición <code>x</code> e <code>y</code> del centro del arco. Corresponderán a las coordenadas del centro de la pelota.</li> + <li>El radio del arco - que vendrá dado por la propiedad de tamaño <code>size</code> de la pelota.</li> + <li>Los últimos dos parámetros especifican el comienzo y final del arco en radianes. En este caso se especifican 0 y <code>2*PI</code> . Que corresponden a 0 y 360 grados. Esto es un circulo completo. Si se quisiese especificar únicamente medio círculo, 180 grados, se especificaría <code>PI</code>.</li> + </ul> + </li> + <li>Por último con el método <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> se finaliza el dibujo, y rellena el área de la curva especificada, según se indico con el <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code>. </li> +</ul> + +<p>Ya se puede empezar a testear el objeto.</p> + +<ol> + <li>Guarde el código hasta ahora, y cargue el archivo HTML en un navegador.</li> + <li>Abra la consola de JavaScript en el navegador, y refresque la página, para que el tamaño del <em>canvas</em> modifique sus dimensiones adaptándose al <em>viewport</em> con la consola abierta. </li> + <li>Teclee lo siguiente en la consola para crear una nueva pelota. + <pre class="brush: js">var testBall = new Ball(50, 100, 4, 4, 'blue', 10);</pre> + </li> + <li>Pruebe a llamar a las variables miembro: + <pre class="brush: js">testBall.x +testBall.size +testBall.color +testBall.draw()</pre> + </li> + <li>Al teclear la última línea, debería ver que la pelota se dibuja en alguna parte del <em>canvas</em>. </li> +</ol> + +<h3 id="Actualizando_los_datos_de_la_pelota">Actualizando los datos de la pelota</h3> + +<p>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 <code>update()</code> en el prototipo de la clase <code>Ball()</code></p> + +<pre class="brush: js">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; +}</pre> + +<p>Las cuatro primeras partes de la función verifican si la pelota a alcanzado el borde del <em>canvas</em>. 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, (<code>velY</code> positiva) , entonces la velocidad vertical es cambiada, para que se mueva hacia abajo (<code>velY</code> negativa).</p> + +<p>Los cuatro posibles casos son: </p> + +<ul> + <li>Verificar si la coordenada <code>x</code> es mayor que el ancho del <em>canvas</em> (la pelota está saliendo por el borde derecho).</li> + <li>Verificar si la coordenada <code>x</code> es menor que la coordenada 0 (la pelota está saliendo por el borde izquierdo)</li> + <li>Verificar si la coordenada <code>y</code> es mayor que la altura del <em>canvas</em> (la pelota está saliendo por el borde inferior).</li> + <li>Verificar si la coordenada <code>y</code> es menor que la coordenada 0 ( la pelota está saliendo por el borde superior).</li> +</ul> + +<p>En cada caso, se ha tenido en cuenta el tamaño (<code>size</code>) de la pelota en los cálculos, ya que las coordenadas <code>x</code> e <code>y</code> corresponden al centro de la pelota, pero lo que queremos ver es el borde de la pelota cuando choca con el perímetro del <em>canvas</em> — que la pelota rebote, cuando está a medio camino fuera de el —.</p> + +<p>Las dos últimas líneas de código, suman la velocidad en x (<code>velX</code>) al valor de la coordenada <code>x</code> , y el valor de la velocidad en y (<code>velY</code>) a la coordenada <code>y</code> — con esto se consigue el efecto de que la pelota se mueva cada vez que este método es llamado. </p> + +<p>Llegados a este punto: ¡continuemos, con las animaciones!</p> + +<h2 id="Animando_las_pelotas">Animando las pelotas</h2> + +<p>Hagamos esto divertido! Ahora vamos a empezar a añadir pelotas al canvas, y animándolas.</p> + +<p>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. </p> + +<pre class="brush: js" dir="rtl">var balls = [];</pre> + +<p>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. </p> + +<p>2. Añadamos las siguientes instrucciones al final del código: </p> + +<pre class="brush: js">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); +}</pre> + +<p>Nuestra función de bucle: <code>loop()</code>, hace lo siguiente: </p> + +<ul> + <li>Define el color de relleno del canvas como negro semi-transparente, entonces dibuja un rectángulo en todo el ancho y alto del canvas, usando <code>fillRect()</code>, (los cuatro parámetros definen las coordenadas de origen, el ancho y el alto del rectángulo). Esto es para cubrir el dibujo del instante anterior antes de actualizar el nuevo dibujo. Si no se realiza este paso, resultará en las imágenes se irán apilando y veremos una especie de serpientes según se mueven por el canvas en vez de las pelotas moviéndose! El color de relleno se define como semitransparente, <code>rgba(0,0,0,0.25)</code>, lo que nos permite que podamos intuir algunos de los dibujos de instantes anteriores, con lo que podremos recrear un poco el efecto de estelas detrás de las pelotas, según se mueven. Pruebe a variar este número para ver como resulta el efecto. </li> + <li>Se crea una nueva instancia de la pelota <code>Ball()</code> usando un número aleatorio mediante la función <code>random()</code>, entonces se añade este elemento al final del arreglo de las pelotas, <code>push()</code>, pero unicamente si el número de pelotas es menor que 25. Así cuando tengamos 25 pelotas en la pantalla, no crearemos nuevas pelotas. Pruebe a variar el número de pelotas en el código: <code>balls.length < 25</code>. Dependiendo de la capacidad de procesamiento del navegador, un número de pelotas muy alto podría ralentizar significativamente la animación. ¡asi que cuidado! </li> + <li>Se recorre el bucle por todo el conjunto de pelotas <code>balls</code> y se ejecuta el método para dibujar, <code>draw()</code>, cada una de las pelotas, y actualizar sus datos, <code>update()</code>, en cada una de ellas, así se conservarán las nuevas posiciones y velocidades para el siguiente intervalo de animación.</li> + <li>Se ejecuta la función de nuevo mediante el método <code>requestAnimationFrame()</code> - cuando este método está continuamente ejecutándose y llama a la misma función, esto ejecutará la función de animación un determinado número de veces por segundo para crear una animación fluida. Esto se realiza normalmente de forma recursiva — lo que quiere decir que la función se llama a sí misma cada vez que se ejecuta, de esa manera se ejecutará una y otra vez de forma continua. </li> +</ul> + +<p>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. </p> + +<pre class="brush: js">loop();</pre> + +<p>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!</p> + +<h2 id="Añadiendo_la_detección_de_colisiones">Añadiendo la detección de colisiones</h2> + +<p>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.</p> + +<ol> + <li>El primer paso, será añadir el código a continuación a continuación de donde se definió el método <code>update()</code>. (en código de <code>Ball.prototype.update</code>) + + <pre class="brush: js">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) +')'; + } + } + } +}</pre> + + <p>Esta función es un poco complicada, así que no hay que preocuparse mucho si de momento no se comprende del todo. </p> + + <ul> + <li>Para cada pelota, necesitamos comprobar si chocará con cada una de las otras pelotas. Para esto, en un bucle <code>for</code> para recorrer todas las pelotas.</li> + <li>Dentro del bucle, usamos un <code>if</code> para comprobar si la pelota que estamos mirando en ese ciclo del bucle <code>for</code> 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 <code>!</code> 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.</li> + <li>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 <a href="/en-US/docs/Games/Techniques/2D_collision_detection">detección de colision 2D</a>.</li> + <li>En este caso, únicamente se define la propiedad de <code>color</code> 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 <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a>, <a href="http://brm.io/matter-js/">matter.js</a>, <a href="http://phaser.io/">Phaser</a>, etc.</li> + </ul> + </li> + <li>También es necesario llamar este método en cada instante de la animación. <code>balls[i].update();</code> en la línea: + <pre class="brush: js">balls[i].collisionDetect();</pre> + </li> + <li>Guardar y refrescar la demo de nuevo y podrá ver como las pelotas cambian de color cuando chocan entre ellas.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas para hacer funcionar este ejemplo, puede comparar su código JavaScript, con el código de la <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">version_final</a> (y también ver como funciona al <a href="http://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">ejecutarla</a>).</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>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. </p> + +<h2 id="Lea_también">Lea también</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Canvas tutorial</a> — una guia de principiante para usar el canvas 2D.</li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></li> + <li><a href="/en-US/docs/Games/Techniques/2D_collision_detection">2D detección de colisiones</a></li> + <li><a href="/en-US/docs/Games/Techniques/3D_collision_detection">3D detección de colisiones</a></li> + <li><a href="/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript">2D juego de ruptura usando sólo JavaScript</a> — un gran tutorial para principiantes sobre como construir un juego 2D.</li> + <li><a href="/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser">2D juego de ruptura usando Phaser</a> — explica los conceptos fundamentales para construir un juego 2D usando una librería de juegos de JavaScript. </li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Conceptos básicos de los objetos JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientado a objetos para principiantes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de objetos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Ejercicio práctico de construcción de objetos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Añadiendo características a nuestra demo de bouncing balls</a></li> +</ul> 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 +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">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.</p> + +<h3 id="¿Buscas_convertirte_en_desarrollador_web_de_front-end">¿Buscas convertirte en desarrollador web de front-end?</h3> + +<p class="summary">Hemos puesto un curso que incluye toda la información esencial que necesitas para alcanzar esa meta</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Comienza aquí</a></p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de empezar este módulo deberías estar familiarizado con {{Glossary("HTML")}} and {{Glossary("CSS")}}. Te aconsejamos trabajar los módulos <a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML"> Introducción a HTML</a> y <a href="https://developer.mozilla.org/es/docs/Learn/CSS/Introduction_to_CSS">Introducción a CSS</a> antes de empezar con JavaScript.</p> + +<p>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 <a href="/es/docs/Learn/JavaScript/First_steps">Primeros pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Elementos básicos de JavaScript</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: 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 <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Basics">Principios básicos de los Objetos</a></dt> + <dd>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.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript Orientado a Objetos para principiantes</a></dt> + <dd>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.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de Objetos</a></dt> + <dd>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.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></dt> + <dd><span id="result_box" lang="es"><span>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".</span> <span>Además, presentamos algunos consejos sobre cuándo y dónde puede usar OOJS.</span></span></dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></dt> + <dd><span id="result_box" lang="es"><span>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;</span> <span>se mostrará en una página web).</span> <span>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.</span></span></dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/Ejercicio_práctico_de_construcción_de_objetos">Práctica de Construcción de Objetos</a></dt> + <dd><span id="result_box" lang="es"><span>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.</span> <span>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.</span></span></dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Agregar funciones a nuestra demo de "Pelotas Rebotando"</a></dt> + <dd><span id="result_box" lang="es"><span>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.</span></span></dd> +</dl> + +<h2 id="Vea_también">Vea también</h2> + +<dl> + <dt><a href="https://learnjavascript.online/">Aprender JavaScript</a></dt> + <dd>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.</dd> +</dl> 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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Con la mayoría de los detalles internos de OOJS (<em>JavaScript Orientado a Objetos) </em>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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Conocimientos básicos de informática, una comprensión básica de HTML y CSS, familiaridad con los principios básicos de JavaScript (ver <a href="/en-US/docs/Learn/JavaScript/First_steps">Primeros pasos</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Construyendo bloques</a>) y conceptos básicos de OOJS (ver <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduccion a objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo es posible implementar la herencia en JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Herencia_prototípica">Herencia prototípica</h2> + +<p>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?</p> + +<p>Exploremos cómo hacer esto con un ejemplo concreto.</p> + +<h2 id="Primeros_pasos">Primeros pasos</h2> + +<p>Primero que nada, hazte una copia local de nuestro archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (míralo <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">corriendo en vivo</a> también). Dentro de aquí encontrarás el mismo ejemplo de constructor de <code>Persona()</code> que hemos estado usando a través del módulo, con una ligera diferencia — hemos definido solo las propiedades dentro del constructor:</p> + +<pre class="brush: js notranslate">function Persona(nombrePila, apellido, edad, genero, intereses) { + this.nombre = { + nombrePila, + apellido + }; + this.edad = edad; + this.genero = genero; + this.intereses = intereses; +};</pre> + +<p><em>Todos</em> los métodos están definidos en el prototipo del constructor. Por ejemplo:</p> + +<pre class="brush: js notranslate">Persona.prototype.saludo = function() { + alert('¡Hola! soy ' + this.nombre.nombrePila + '.'); +};</pre> + +<div class="note"> +<p><strong>Nota</strong>: En el código fuente, también verá los métodos <code>bio()</code> y <code>despedida()</code> definidos. Más tarde verá cómo estos pueden ser heredados por otros constructores.</p> +</div> + +<p>Digamos que quisieramos crear una clase de <code>Profesor</code>, como la que describimos en nuestra definición inicial orientada a objetos, que hereda todos los miembros de <code>Persona</code>, pero también incluye:</p> + +<ol> + <li>Una nueva propiedad, <font face="consolas, Liberation Mono, courier, monospace"><span>materia</span></font> — esto contendrá la materia que el profesor enseña.</li> + <li>Un método actualizado de <code>saludo()</code>, que suena un poco más formal que el método estándar de <code>saludo()</code> — más adecuado para un profesor que se dirige a algunos estudiantes en la escuela.</li> +</ol> + +<h2 id="Definiendo_un_constructor_Profesor">Definiendo un constructor Profesor()</h2> + +<p>Lo primero que tenemos que hacer es crear el constructor Profesor<code>()</code> — añadimos lo siguiente tras el código existente:</p> + +<pre class="brush: js notranslate">function Profesor(nombrePila, apellido, edad, genero, intereses, materia) { + Person.call(this, nombrePila, apellido, edad, genero, intereses); + + this.materia = materia; +}</pre> + +<p>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.<br> + 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.</p> + +<p>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().</p> + +<p>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.</p> + +<p>Como nota, podríamos haber simplemente hecho esto:</p> + +<pre class="brush: js notranslate">function Profesor(nombrePila, apellido, edad, genero, intereses, materia) { + this.nombre = { + nombrePila, + apellido + }; + this.edad = edad; + this.genero = genero; + this.intereses = intereses; + this.materia = materia; +}</pre> + +<p>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.</p> + +<h3 id="Heredando_de_un_constructor_sin_parámetros">Heredando de un constructor sin parámetros</h3> + +<p>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 <code>call()</code>. Por ejemplo, si se tuviera algo muy simple como esto:</p> + +<pre class="brush: js notranslate">function Brick() { + this.width = 10; + this.height = 20; +}</pre> + +<p>Se podrían heredar las propiedades <code>width</code> y <code>height</code> haciendo esto (así como los otros pasos descritos a continuación, por supuesto):</p> + +<pre class="brush: js notranslate">function BlueGlassBrick() { + Brick.call(this); + + this.opacity = 0.5; + this.color = 'blue'; +}</pre> + +<p>Nótese que solo especificamos <code>this</code> dentro de <code>call()</code> — no se requieren otros parámetros ya que no estamos heredando ninguna propiedad del padre que sea establecida por parámetros.</p> + +<h2 id="Estableciendo_el_prototipo_de_Profesor_y_su_referencia_al_constructor">Estableciendo el prototipo de Profesor() y su referencia al constructor</h2> + +<p>Todo va bien hasta ahora, pero tenemos un problema. Definimos un nuevo constructor, y tiene una propiedad <code>prototype</code>, la cual por defecto solo contiene una referencia a la función constructor en sí misma. No contiene los métodos de la propiedad <code>prototype</code> del constructor <code>Persona</code>. Para ver esto, introduzca <code>Object.getOwnPropertyNames(Profesor.prototype)</code> ya sea en el campo de texto o en la consola de Javascript . Introdúzcalo nuevamente, reemplazando <code>Profesor</code> con <code>Persona</code>. El nuevo constructor tampoco hereda esos métodos. Para ver esto, compare los resultados de <code>Persona.prototype.saludo</code> and <code>Profesor.prototype.saludo</code>. Necesitamos obtener <code>Profesor()</code> para obtener los métodos definidos en el prototipo de <code>Persona()</code>. ¿Cómo lo hacemos?</p> + +<ol> + <li>Añade la siguiente línea debajo de tu adición anterior: + <pre class="brush: js notranslate">Profesor.prototype = Object.create(Persona.prototype);</pre> + Aquí es cuando nuestro amigo <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> sale al rescate de nuevo. En este caso lo estamos usando para crear un nuevo objeto y hacerlo el valor de <code>Profesor.prototype.</code> El nuevo objeto tiene <code>Persona.prototype</code> como su prototipo y por lo tanto heredará, si y cuando lo necesite, todos los métodos disponibles en <code>Persona.prototype</code>.</li> + <li>Necesitamos hacer una cosa más antes de proseguir. Después de agregar la última línea, la propiedad <code>constructor </code>de <code>Profesor.prototype</code> es ahora igual a <code>Persona()</code>, debido a que acabamos de asignar <code>Profesor.prototype</code> para que haga referencia a un objeto que hereda sus propiedades de <code>Persona.prototype</code>! Ahora prueba guardando tu código, carga la página en un explorador e intenta verificar en la consola el valor de <code>Profesor.prototype.constructor</code>.</li> + <li>Esto puede volverse un problema, así que necesitamos corregirlo. Puedes hacerlo regresando a tu código y agregando la siguiente línea al final: + <pre class="brush: js notranslate">Profesor.prototype.constructor = Profesor;</pre> + </li> + <li>Ahora, si guardas y actualizas, el valor de <code>Profesor.prototype.constructor</code> debe regresar <code>Profesor()</code>, como se espera, además de que ahora estamos heredando de <code>Persona()</code>!</li> +</ol> + +<h2 id="Dándole_a_Profesor_un_nuevo_método_saludo">Dándole a Profesor() un nuevo método saludo()</h2> + +<p>Para finalizar nuestro código, necesitamos definir un nuevo método <code>saludo()</code> en el constructor de <code>Profesor()</code>.</p> + +<p>La manera más fácil es definirlo en el prototipo de <code>Profesor()</code> — agrega lo siguiente al final de tu código:</p> + +<pre class="brush: js notranslate">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 + '.'); +};</pre> + +<p>Esto muestra el saludo del profesor, el cual además utiliza un prefijo apropiado para su género, resuelto utilizando un bloque else-if.</p> + +<h2 id="Probando_el_ejemplo">Probando el ejemplo</h2> + +<p>Ahora que ha ingresado todo el código, intente creando una instancia de objeto desde <code>Profesor()</code> poniendo lo que sigue al final de su archivo (o algo similar a su elección):</p> + +<pre class="brush: js notranslate">var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');</pre> + +<p>Ahora guarde y actualice, e intente accediendo a las propiedades y metodos de su nuevo<code> teacher1</code> objecto, por ejemplo:</p> + +<pre class="brush: js notranslate">teacher1.name.first; +teacher1.interests[0]; +teacher1.bio(); +teacher1.subject; +teacher1.greeting(); +teacher1.farewell();</pre> + +<p>Esto deberia trabajar bien. Las consultas de las líneas 1, 2, 3, y 6 acceden a miembros heredados del genérico<code> Person()</code> constructor (clase). La consulta de la línea 4 accede un miembro que es disponible solamente en el mas especializado<code> Teacher()</code> constructor (clase). La consulta de la línea 5 accedería a un miembro desde<code> Person()</code>, excepto por el hecho que <code>Teacher()</code> tiene sus propios miembros con el mismo nombre, entonces la consulta accede a ese miembro.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas con el funcionamiento, compare su código con nuestra <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">versión final</a> (vea <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">corriendo en vivo</a> también).</p> +</div> + +<p>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.</p> + +<p>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 <a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a>). 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.</p> + +<p>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. <a href="http://coffeescript.org/#classes">CoffeeScript</a> por ejemplo provee<code> class</code>, <code>extends</code>, etc.</p> + +<h2 id="Un_ejercicio_mas_allá">Un ejercicio mas allá</h2> + +<p>En nuestra <a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">Sección teórica de POO</a>, también incluimos una clase <code>Student</code> como un concepto, el cual hereda todas las características de <code>Person</code>, y también tiene un método diferende de <code>greeting()</code> que <code>Person</code> que es mas informal que el saludo de los profesores <code>Teacher</code>. Dele una mirada al saludo de los estudiantes, y trate de implementar su propio constructor de saludo <code>Student()</code> que herede todas las características de <code>Person()</code>, e implemente las diferentes funciones de saludo <code>greeting()</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas resolviendo esto, dele una mirada a nuestra<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html"> versión final</a> (véala tambien <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">funcionando</a> ).</p> +</div> + +<h2 id="Resúmen_de_miembros_objeto">Resúmen de miembros objeto</h2> + +<p>To summarize, you've basically got three types of property/method to worry about:</p> + +<ol> + <li>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 <code>this.x = x</code> type lines; in built in browser code, they are the members only available to object instances (usually created by calling a constructor using the <code>new</code> keyword, e.g. <code>var myInstance = new myConstructor()</code>).</li> + <li>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, <em>not</em> an instance. For example, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>.</li> + <li>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. <code>myConstructor.prototype.x()</code>.</li> +</ol> + +<p>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.</p> + +<h2 id="ECMAScript_2015_Classes">ECMAScript 2015 Classes</h2> + +<p>ECMAScript 2015 introduces <a href="/en-US/docs/Web/JavaScript/Reference/Classes">class syntax</a> 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.</p> + +<div class="note"> +<p><strong>Note</strong>: 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).</p> +</div> + +<p>Let's look at a rewritten version of the Person example, class-style:</p> + +<pre class="brush: js notranslate">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!`); + }; +} +</pre> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/class">class</a> statement indicates that we are creating a new class. Inside this block, we define all the features of the class:</p> + +<ul> + <li>The <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/constructor">constructor()</a></code> method defines the constructor function that represents our <code>Person</code> class.</li> + <li><code>greeting()</code> and <code>farewell()</code> are class methods. Any methods you want associated with the class are defined inside it, after the contructor. In this example, we've used <a href="/en-US/docs/Web/JavaScript/Reference/Template_literals">template literals</a> rather than string concatenation to make the code easier to read.</li> +</ul> + +<p>We can now instantiate object instances using the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/new"><code>new</code> operator</a>, in just the same way as we did before:</p> + +<pre class="brush: js notranslate">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 +</pre> + +<div class="note"> +<p><strong>Note</strong>: 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.</p> +</div> + +<h3 id="Inheritance_with_class_syntax">Inheritance with class syntax</h3> + +<p>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 <code>Teacher</code> class, making it inherit from <code>Person</code> using modern class syntax. This is called creating a subclass or subclassing.</p> + +<p>To create a subclass we use the <a href="/en-US/docs/Web/JavaScript/Reference/Classes/extends">extends keyword</a> to tell JavaScript the class we want to base our class on.</p> + +<pre class="brush: js notranslate">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; + } +}</pre> + +<p>We can make the code more readable by defining the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/super"><code>super()</code> operator</a> as the first item inside the <code>constructor()</code>. This will call the parent class' constructor, and inherit the members we specify as parameters of <code>super()</code>, as long as they are defined there:</p> + +<pre class="brush: js notranslate">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; + } +} +</pre> + +<p>When we instantiate <code>Teacher</code> object instances, we can now call methods and properties defined on both <code>Teacher</code> and <code>Person</code>, as we'd expect:</p> + +<pre class="brush: js notranslate">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 +</pre> + +<p>Like we did with Teachers, we could create other subclasses of <code>Person</code> to make them more specialized without modifying the base class.</p> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-class-inheritance.html">es2015-class-inheritance.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-class-inheritance.html">see it live also</a>).</p> +</div> + +<h2 id="Getters_and_Setters">Getters and Setters</h2> + +<p>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 <code>Teacher</code> example, we may not know what subject the teacher will teach before we create them, or their subject may change between terms.</p> + +<p>We can handle such situations with getters and setters.</p> + +<p>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.</p> + +<p>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.</p> + +<p>The modified <code>Teacher</code> class looks like this:</p> + +<pre class="brush: js notranslate">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; + } +} +</pre> + +<p>In our class above we have a getter and setter for the <code>subject</code> property. We use <strong><code>_</code> </strong> 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:</p> + +<ul> + <li>To show the current value of the <code>_subject</code> property of the <code>snape</code> object we can use the <code>snape.subject</code> getter method.</li> + <li>To assign a new value to the <code>_subject</code> property we can use the <code>snape.subject="new value"</code> setter method.</li> +</ul> + +<p>The example below shows the two features in action:</p> + +<pre class="brush: js notranslate">// 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" +</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-getters-setters.html">es2015-getters-setters.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-getters-setters.html">see it live also</a>).</p> +</div> + +<h2 id="When_would_you_use_inheritance_in_JavaScript">When would you use inheritance in JavaScript?</h2> + +<p>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.</p> + +<p>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.</p> + +<p>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.</p> + +<div class="note"> +<p><strong>Note</strong>: Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called <strong>delegation</strong>. Specialized objects delegate functionality to a generic object type.</p> +</div> + +<p>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.</p> + +<p>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.</p> + +<h2 id="Alternativas_para_extender_la_cadena_del_prototipos">Alternativas para extender la cadena del prototipos</h2> + +<p>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 <a href="/es/docs/Web/JavaScript/Herencia_y_la_cadena_de_protipos">Herencia y la cadena de prototipos</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>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.</p> + +<p>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.</p> + +<h2 id="Véase_también">Véase también</h2> + +<ul> + <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — A really useful interactive learning site for learning about objects.</li> + <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapter 6 — A good book on advanced JavaScript concepts and techniques, by John Resig and Bear Bibeault. Chapter 6 covers aspects of prototypes and inheritance really well; you can probably track down a print or online copy fairly easily.</li> + <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this & Object Prototypes</a> — Part of Kyle Simpson's excellent series of JavaScript manuals, Chapter 5 in particular looks at prototypes in much more detail than we do here. We've presented a simplified view in this series of articles aimed at beginners, whereas Kyle goes into great depth and provides a more complex but more accurate picture.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_éste_módulo">En éste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> 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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Alfabetismo computacional básico, una comprensión básica de HTML y CSS, familiaridad con los temas básicos de JavaScript (vea <a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) y OOJS básico (vea <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo trabajar con datos almacenados en JSON, y crear objetos JSON propios.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_realmente_JSON">¿Qué es realmente JSON?</h2> + +<p>{{glossary("JSON")}} es un formato de datos basado en texto que sigue la sintaxis de objeto de JavaScript, popularizado por <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Douglas Crockford</a>. 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; <em>parsear</em>) y generar JSON.</p> + +<p>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 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> que tiene los métodos disponibles para convertir entre ellos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Convertir una cadena a un objeto nativo se denomina <em>parsing</em>, mientras que convertir un objeto nativo a una cadena para que pueda ser transferido a través de la red se denomina <em>stringification</em>.</p> +</div> + +<p>Un objeto JSON puede ser almacenado en su propio archivo, que es básicamente sólo un archivo de texto con una extension <code>.json</code>, y una {{glossary("MIME type")}} de <code>application/json</code>.</p> + +<h3 id="Estructura_del_JSON">Estructura del JSON</h3> + +<p>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:</p> + +<pre class="brush: json">{ + "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" + ] + } + ] +}</pre> + +<p>Si se carga este objeto en un programa de JavaScript, convertido (<em>parseado</em>) en una variable llamada <code>superHeroes</code> 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 <a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a>. Por ejemplo:</p> + +<pre class="brush: js">superHeroes.homeTown +superHeroes['active']</pre> + +<p>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: </p> + +<pre class="brush: js">superHeroes['members'][1]['powers'][2]</pre> + +<ol> + <li>Primero el nombre de la variable — <code>superHeroes</code>.</li> + <li>Dentro de esta variable para acceder a la propiedad <code>members</code> utilizamos <code>["members"]</code>.</li> + <li><code>members</code> contiene un arreglo poblado por objetos. Para acceder al segundo objeto dentro de este arreglo se utiliza <code>[1]</code>.</li> + <li>Dentro de este objeto, para acceder a la propiedad <code>powers</code> utilizamos <code>["powers"]</code>.</li> + <li>Dentro de la propiedad <code>powers</code> existe un arreglo que contiene los superpoderes del héroe seleccionado. Para acceder al tercer superpoder se utiliza <code>[2]</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: El JSON previamente visto se encuentra disponible dentro de una variable en el ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONTest.html</a> (vea el <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">código fuente</a>). Intente cargarlo y luego acceder a los datos contenidos en la variable por medio de la consola JavaScript de su navegador.</p> +</div> + +<h3 id="Arreglos_como_JSON">Arreglos como JSON</h3> + +<p>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:</p> + +<pre class="brush: json">[ + { + "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" + ] + } +]</pre> + +<p>Éste es un JSON perfectamente válido. Para acceder a esta version convertida se debe comenzar con un índice de arreglo, por ejemplo<code>[0]["powers"][0]</code>.</p> + +<h3 id="Otras_notas">Otras notas</h3> + +<ul> + <li>JSON es sólo un formato de datos — contiene sólo propiedades, no métodos.</li> + <li>JSON requiere usar comillas dobles para las cadenas y los nombres de propiedades. Las comillas simples no son válidas.</li> + <li>Una coma o dos puntos mal ubicados pueden producir que un archivo JSON no funcione. Se debe ser cuidadoso para validar cualquier dato que se quiera utilizar (aunque los JSON generados por computador tienen menos probabilidades de tener errores, mientras el programa generador trabaje adecuadamente). Es posible validar JSON utilizando una aplicación como <a href="http://jsonlint.com/">JSONLint</a>.</li> + <li>JSON puede tomar la forma de cualquier tipo de datos que sea válido para ser incluido en un JSON, no sólo arreglos u objetos. Así, por ejemplo, una cadena o un número único podrían ser objetos JSON válidos.</li> + <li>A diferencia del código JavaScript en que las propiedades del objeto pueden no estar entre comillas, en JSON, sólo las cadenas entre comillas pueden ser utilizadas como propiedades.</li> +</ul> + +<h2 id="Aprendizaje_activo_Trabajando_a_través_de_un_ejemplo_de_JSON">Aprendizaje activo: Trabajando a través de un ejemplo de JSON</h2> + +<p>A continuación se muestra un ejemplo de cómo podemos utilizar algunos datos JSON en un sitio web.</p> + +<h3 id="Para_comenzar">Para comenzar</h3> + +<p>Haga una copia local de los archivos <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a>. El último contiene un CSS simple para dar estilo a la página, mientras el primero contiene un HTML muy sencillo:</p> + +<pre class="brush: html"><header> +</header> + +<section> +</section></pre> + +<p>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:</p> + +<pre class="brush: js">const header = document.querySelector('header'); +const section = document.querySelector('section');</pre> + +<p>Los datos JSON se encuentran disponibles en GitHub en el siguiente enlace: <a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>.</p> + +<p>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:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13857/json-superheroes.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Obteniendo_el_JSON">Obteniendo el JSON</h3> + +<p>Para obtener el JSON se utilizará un API llamado {{domxref("XMLHttpRequest")}} (a menudo llamado <strong>XHR</strong>). É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.</p> + +<ol> + <li>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: + <pre class="brush: js">const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> + </li> + <li>Para crear una solicitud, se necesita crear una nueva instancia de objeto de solicitud desde el constructor<code>XMLHttpRequest</code>, utilizando la palabra clave <code>new</code>. Agregue lo siguiente a continuación de la última línea: + <pre class="brush: js">const request = new XMLHttpRequest();</pre> + </li> + <li>Ahora es necesario abrir una nueva solicitud utilizando el método <code><a href="/en-US/docs/Web/API/XMLHttpRequest/open">open()</a></code>. Agregue la siguiente línea: + <pre class="brush: js">request.open('GET', requestURL);</pre> + + <p>Esto requiere al menos dos parámetros — Existen otros parámetros opcionales disponibles. Sólo se requieren los dos obligatorios para este ejemplo:</p> + + <ul> + <li>El método HTTP a usar cuando se hace una solicitud en red. En este caso <code>GET</code> es adecuado, dado que sólo se estan recuperando algunos datos simples.</li> + <li>La URL a la que se realiza la solicitud — esta es la URL del archivo que se almacenó antes.</li> + </ul> + </li> + <li>Luego, agregue las siguientes dos lineas — establecemos el <code><a href="/en-US/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code> 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 <code><a href="/en-US/docs/Web/API/XMLHttpRequest/send">send()</a></code>: + <pre class="brush: js">request.responseType = 'json'; +request.send();</pre> + </li> + <li>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: + <pre class="brush: js">request.onload = function() { + const superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + </li> +</ol> + +<p>En este punto se está almacenando la respuesta a la solicitud (disponible en la propiedad <code><a href="/en-US/docs/Web/API/XMLHttpRequest/response">response</a></code>) en una variable llamada <code>superHeroes</code>; 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 <<code>header></code> con los datos correctos, mientras la segunda creará una tarjeta de información para cada héroe en el equipo y la insertará en <code><section></code>.</p> + +<p>Se ha contenido el código en un manejador de eventos que se activa cuando se dispara el evento de carga (ver <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) — esto es porque el evento de carga se dispara cuando la respuesta ha sido retornada de forma exitosa; de esta manera se garantiza que <code>request.response</code> estará disponible cuando se intente hacer algo con ella.</p> + +<h3 id="Poblando_el_encabezado">Poblando el encabezado</h3> + +<p>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:</p> + +<pre class="brush: js">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); +}</pre> + +<p>Se ha llamado al parámetro <code>jsonObj</code>, para recordar que este es un objeto JavaScript originado desde un JSON. Primero se crea un elemento {{HTMLElement("h1")}} con <code><a href="/en-US/docs/Web/API/Document/createElement">createElement()</a></code>, se asigna su <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> igual a la propiedad <code>squadName</code> del objeto, luego se agrega al encabezado utilizando<code><a href="/en-US/docs/Web/API/Node/appendChild">appendChild()</a></code>. 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 <code>homeTown</code> y <code>formed</code> del objeto.</p> + +<h3 id="Creación_de_las_tarjetas_de_información_del_héroe">Creación de las tarjetas de información del héroe</h3> + +<p>Luego, agregue la siguiente función al final del código, que crea y muestra las tarjetas de los superhéroes:</p> + +<pre class="brush: js">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); + } +}</pre> + +<p>Para empezar, se almacena la propiedad <code>members</code> del objeto JavaScript en una nueva variable. Este arreglo contiene múltiples objetos que contienen la información para cada héroe.</p> + +<p>A continuación, se utiliza un ciclo <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for</a> para recorrer cada objeto en el arreglo. Para cada uno:</p> + +<ol> + <li>Se crean varios elementos nuevos: un<code><article></code>, un <code><h2></code>, tres <code><p></code>s, y una <code><ul></code>.</li> + <li>Se asigna al <code><h2></code> para que muestre el <code>name</code> del héroe.</li> + <li>Se completan los tres párrafos con su <code>secretIdentity</code>, <code>age</code>, y una línea que diga "Superpowers:" para introducir la información de la lista.</li> + <li>Se almacena la propiedad <code>powers</code> en otra variable nueva llamada <code>superPowers</code> — que contiene un arreglo que lista los superpoderes del héroe actual.</li> + <li>Para recorrer los superpoderes del héroe, se utiliza otro ciclo <code>for</code> — para cada uno se crea un elemento <code><li></code>, se asigna el superpoder a él y luego se pone el <code>listItem</code> dentro del elemento <code><ul></code> (<code>myList</code>) utilizando <code>appendChild()</code>.</li> + <li>Lo último es agregar los <code><h2></code>, <code><p></code>s, y <code><ul></code> dentro del <code><article></code> (<code>myArticle</code>), luego se agrega <code><article></code> dentro de <code><section></code>. El orden en que las cosas son agregadas es importante, dado que este es el orden en el que aparecerán dentro del HTML.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas en lograr que el ejemplo funcione, intente con el código fuente <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> (vea también <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">running live</a>.)</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: 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 <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> 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 <a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a> para mayor información sobre la notación de punto y corchete.</p> +</div> + +<h2 id="Conversiones_entre_objetos_y_texto">Conversiones entre objetos y texto</h2> + +<p>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:</p> + +<pre class="brush: js">request.responseType = 'json';</pre> + +<p>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:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code>: Acepta una cadena JSON como parámetro, y devuelve el objeto JavaScript correspondiente.</li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code>: Acepta un objeto como parámetro, y devuelve la forma de cadena JSON equivalente.</li> +</ul> + +<p>El primer método se puede observar en el ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> (vea el <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">código fuente</a>) — 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 <code>parse()</code> para convertirlo en un objeto JavaScript. El extracto del código es el siguiente:</p> + +<pre class="brush: js">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); +}</pre> + +<p>Como es de suponer, <code>stringify()</code> trabaja de la forma opuesta. Intente ingresar las siguientes líneas en la consola de JavaScript de su navegador para verlo en acción:</p> + +<pre class="brush: js">const myJSON = { "name": "Chris", "age": "38" }; +myJSON +const myString = JSON.stringify(myJSON); +myString</pre> + +<p>En este caso, se ha creado un objeto JavaScript, luego se comprueba lo que contiene, y entonces se convierte en una cadena JSON utilizando <code>stringify()</code> — guardando el valor retornado en una variable nueva — y comprobándolo nuevamente.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>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.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/HTTP/Methods">HTTP request methods</a></li> + <li><a href="http://json.org">Official JSON web site with link to ECMA standard</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> 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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de computación, entendimiento básico de HTML y CSS, familiaridad con las bases de Javascript (ver <a href="/es/docs/Learn/JavaScript/First_steps">Primeros pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Bloques de construcción JavaScript</a>) y las bases de JSOO (ver <a href="/es/docs/Learn/JavaScript/Objects/Basics">Introducción a objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>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.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Programacion_Orientada_a_Objetos—_lo_básico">Programacion Orientada a Objetos— lo básico</h2> + +<p>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.</p> + +<p>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 <strong>encapsular</strong>) dentro del paquete de un objeto (al que se puede asignar un nombre específico, llamado a veces <strong>espacio de nombres</strong>), 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.</p> + +<h3 id="Definiendo_una_plantilla_de_objeto">Definiendo una plantilla de objeto</h3> + +<p>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.</p> + +<p>Para empezar, podríamos volver a ver al objeto <code>Persona</code> de nuestro <a href="/es/docs/Learn/JavaScript/Objects/Basics">artículo de primeros objetos</a>, 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. </p> + +<p>Esto es conocido como <strong>abstracción</strong> — 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.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13889/person-diagram.png" style="display: block; height: 219px; margin: 0px auto; width: 610px;"></p> + +<p>En algunos lenguajes de POO, esta definición de tipo de objeto se la llama <strong>class </strong>(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.</p> + +<h3 id="Creando_objetos">Creando objetos</h3> + +<p>Partiendo de nuestra clase, podemos crear <strong>instancias de objetos</strong> — objetos que contienen los datos y funcionalidades definidas en la clase original. Teniendo a nuestra clase <code>Persona</code>, ahora podemos crear gente con características más específicas: </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15163/MDN-Graphics-instantiation-2-fixed.png" style="display: block; height: 702px; margin: 0px auto; width: 695px;"></p> + +<p>Cuando una instancia del objeto es creada a partir de una clase, se ejecuta <strong>la función constructora </strong>(constructor en inglés) de la clase para crearla. El proceso de crear una instancia del objeto desde una clase se llama <strong>instanciación</strong>.</p> + +<h3 id="Clases_especializadas">Clases especializadas</h3> + +<p>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 <strong>clases secundarias</strong> se pueden hacer para <strong>heredar</strong> los datos y código de su <strong>clase primaria</strong>, 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.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13881/MDN-Graphics-inherited-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>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).</p> + +<div class="note"> +<p><strong>Nota: </strong>la palabra elegante para la capacidad de múltiples tipos de objetos de implementar la misma funcionalidad es <strong>polimorfismo. </strong>Por si acaso te preguntabas.</p> +</div> + +<p>Ahora puedes crear instancias de objetos de las clases "hijo". Por ejemplo:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13885/MDN-Graphics-instantiation-teacher-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>En el resto del articulo, comenzaremos a ver como podemos practicar la teoría de POO en JavaScript.</p> + +<h2 id="Constructores_e_instancias_de_objetos">Constructores e instancias de objetos</h2> + +<p>Algunas personas sostienen que JavaScript no es un verdadero lenguaje orientado a objetos — por ejemplo, su enunciado <code><a href="/es/docs/Web/JavaScript/Reference/Statements/class">class</a></code> es sólo azúcar sintáctica sobre la herencia prototípica existente y no es una <code>class</code> 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.</p> + +<p>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 <a href="/es/docs/Learn/JavaScript/Objects/Object_prototypes">artículo Prototipos</a> 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.</p> + +<div class="note"> +<p><strong>Nota: </strong>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.</p> +</div> + +<p>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 <code>oojs.html</code> que vimos en nuestro primer artículo de Objetos.</p> + +<h3 id="Un_ejemplo_simple">Un ejemplo simple</h3> + +<ol> + <li>Comencemos por ver cómo puedes definir una persona con una funcion normal. Agrega esta funcion dentro del elemento <code>script</code>: + + <pre class="brush: js notranslate">function createNewPerson(name) { + var obj = {}; + obj.name = name; + obj.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; + return obj; +}</pre> + </li> + <li>Ahora puedes crear una nueva persona llamando a esta funcion — prueba con las siguientes lineas en la consola Javascript de tu navegador: + <pre class="brush: js notranslate">var salva = createNewPerson('Salva'); +salva.name; +salva.greeting();</pre> + 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!</li> + <li>Reemplaza tu función anterior por la siguiente: + <pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + </li> +</ol> + +<p>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 <code>this</code> se está usando aquí también — es básicamente decir que cuando se crea una de estas instancias de objeto, la propiedad <code>name</code> del objeto será igual al valor del nombre pasado a la llamada del constructor, y el método <code>greeting()</code> usará también el valor del nombre pasado a la llamada del constructor.</p> + +<div class="note"> +<p><strong>Nota</strong>: 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.</p> +</div> + +<p>Entonces, ¿cómo llamamos a un constructor para crear algunos objetos?</p> + +<ol> + <li>Agrega las siguientes líneas debajo de tu código anterior: + <pre class="brush: js notranslate">var person1 = new Person('Bob'); +var person2 = new Person('Sarah');</pre> + </li> + <li>Guarda el código y vuelve a cargarlo en el navegador, e intenta ingresar las siguientes líneas en la consola Javascript : + <pre class="brush: js notranslate">person1.name +person1.greeting() +person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>¡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 <code>person1</code> o <code>person2</code>; 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 <code>greeting()</code>. Ten en cuenta que están utilizando su propio <code>name</code> que se les asignó cuando se crearon; esta es una razón por la cual es muy importante usar <code>this</code>, para que usen sus propios valores, y no algún otro valor.</p> + +<p>Veamos nuevamente las llamadas del constructor:</p> + +<pre class="brush: js notranslate">var person1 = new Person('Bob'); +var person2 = new Person('Sarah');</pre> + +<p>En cada caso, la palabra clave <code>new</code> 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:</p> + +<pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + +<p>Una vez creados los nuevos objetos, las variables <code>person1</code> y <code>person2</code> contienen los siguientes objetos:</p> + +<pre class="brush: js notranslate">{ + name: 'Bob', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +} + +{ + name: 'Sarah', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +}</pre> + +<p>Ten en cuenta que cuando llamamos a nuestra función constructora, estamos definiendo <code>greeting()</code> cada vez, lo cual no es lo ideal. Para evitar esto, podemos definir funciones en el prototipo, que veremos más adelante.</p> + +<h3 id="Creando_nuestro_constructor_final">Creando nuestro constructor final</h3> + +<p>El ejercicio que vimos anteriormente fue solo un ejemplo simple para comenzar. Ahora crearemos nuestra función <code>constructor Person()</code> final.</p> + +<ol> + <li>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: + <pre class="brush: js notranslate">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 + '.'); + }; +}</pre> + </li> + <li>Ahora, agrega la siguiente línea para crear una instancia del objeto: + <pre class="brush: js notranslate">var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);</pre> + </li> +</ol> + +<p>Ahora verás que puedes acceder a las propiedades y métodos justo como lo hiciste anteriormente — intenta esto en tu consola JS:</p> + +<pre class="brush: js notranslate">person1['age'] +person1.interests[1] +person1.bio() +// etc.</pre> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes problemas para lograr que funcione, puedes comparar tu código con nuestra versión — ve <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a> (también lo puedes ver <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">corriendo en vivo</a>).</p> +</div> + +<h3 id="Ejercicios_adicionales">Ejercicios adicionales</h3> + +<p>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.</p> + +<p>Además, hay un par de problemas con nuestro método <code>bio()</code> — la salida siempre incluye el pronombre "He", incluso para personas de otros géneros. Y <code>bio</code> solamente incluye dos intereses, sin importar la cantidad que hay en el arreglo <code>interests</code>. ¿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.</p> + +<div class="note"> +<p><strong>Note</strong>: Si estás atascado, hay una <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">respuesta en nuestro repositorio de GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">see it live</a>) — igualmente ¡intentea resolverla primero!</p> +</div> + +<h2 id="Otras_formas_de_crear_instancias_de_objetos">Otras formas de crear instancias de objetos</h2> + +<p>Hasta ahora hemos visto dos diferentes formas de crear una instancia de objeto — <a href="/es/docs/Learn/JavaScript/Objects/Basics#Object_basics">declarando un objeto literal</a>, y usando una función constructora (ver arriba).</p> + +<p>Esto tiene sentido, pero hay otras formas — se muestran aquí para que te vayas familiarizando en caso de encontrarte con ellas.</p> + +<h3 id="El_constructor_Object">El constructor Object()</h3> + +<p>Antes que nada, puedes usar el constructor <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> para crear un nuevo objeto. Si, incluso objetos genéricos tienen un constructor que genera un objeto vacío.</p> + +<ol> + <li>Intenta ingresar este código en la consola JavaScript de tu navegador: + <pre class="brush: js notranslate">var person1 = new Object();</pre> + </li> + <li>Esto guarda un objeto vacío en la variable <code>person1</code>. 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: + <pre class="brush: js notranslate">person1.name = 'Chris'; +person1['age'] = 38; +person1.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); +};</pre> + </li> + <li>También puedes pasar un objeto literal como parámetro al constructor <code>Object()</code>, para precargarlo con propiedades/métodos. Prueba esto en tu consola: + <pre class="brush: js notranslate">var person1 = new Object({ + name: 'Chris', + age: 38, + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +});</pre> + </li> +</ol> + +<h3 id="Usando_el_método_create">Usando el método create()</h3> + +<p>Los constructores te pueden ayudar a ordenar tu código — puedes crear constructores en un lugar, y luego crear instancias cuando sean necesarias.</p> + +<p>Sin embargo, algunas personas prefieren crear instancias de objetos sin crear antes constructores, especialmente si van a crear solamente pocas instancias de un objeto.</p> + +<p>JavaScript tiene un método llamado <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> que permite hacer esto. Con este método puedes crear un nuevo objeto basado en cualquier otro objeto existente.</p> + +<ol> + <li>Con tu ejercicio de la sección anterior cargado en el navegador, prueba esto en tu consola JavaScript + <pre class="brush: js notranslate">var person2 = Object.create(person1);</pre> + </li> + <li>Y ahora prueba esto: + <pre class="brush: js notranslate">person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>Verás que <code>person2</code> fue creado basado en <code>person1 </code>— tiene las mismas propiedades y métodos.</p> + +<p>Una limitación del método <code>create()</code> es que no está soportado por el navegador IE8. Por lo que los constructores serán más efectivos sin necesitas soportar navegadores antiguos.</p> + +<p>Más tarde, exploraremos en detalle los efectos de <code>create()</code>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>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.</p> + +<p>En el próximo artículo, exploraremos los prototipos de objeto JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/Objects/Basics">Objetos básicos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientedo a objetos para principiantes</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de Objetos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object_building_practice">Práctica de construcción de objetos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Agregar funciones a nuestro demo de pelotas que rebotan</a></li> +</ul> 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 +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">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.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitios:</th> + <td>Conocer las funciones en Javascript, conocimientos básicos de Javascript (ver <a href="/en-US/docs/Learn/JavaScript/First_steps">Primeros Pasos</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) y Javascript orientado a Objetos (ver <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introducción a Objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>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.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Un_lenguaje_basado_en_prototipos">¿Un lenguaje basado en prototipos?</h2> + +<p>JavaScript es a menudo descrito como un <strong>lenguaje basado en prototipos - </strong>para proporcionar mecanismos de herencia, los objetos pueden tener un <strong>objeto prototipo</strong>, el cual actúa como un objeto plantilla que hereda métodos y propiedades.</p> + +<p>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 <strong>cadena de prototipos</strong>, y explica por qué objetos diferentes pueden tener disponibles propiedades y métodos definidos en otros objetos.</p> + +<p>Bien, para ser exactos, los métodos y propiedades son definidos en la propiedad <code>prototype</code>, que reside en la función constructora del objeto, no en la instancia misma del objeto.</p> + +<p>En JavaScript, se establece un enlace entre la instancia del objeto y su prototipo (su propiedad <code>__proto__,</code> la cual es derivada de la propiedad <code>prototype</code> sobre el constructor), y las propiedades y metodos son encontrados recorriendo la cadena de prototipos.</p> + +<p><strong>Nota:</strong> Es importante entender que, tanto el prototipo de la instancia de un objeto (al cual se accede mediante <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">Object.getPrototypeOf(obj)</a></code>, o a través de la propiedad <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code>) como el prototipo que contiene el constructor (que se encuentra en la propiedad <code>prototype</code> del constructor) hacen referencia al mismo objeto.</p> + +<p>Vamos a echar un vistazo a algunos ejemplos para intentar aclarar estos conceptos.</p> + +<h2 id="Entendiendo_objectos_prototipos">Entendiendo objectos prototipos</h2> + +<p>Volvamos al ejemplo anterior en el que acabamos definiendo nuestro constructor <code>Person()</code> — 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 <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">código fuente</a>).</p> + +<p>En este ejemplo, hemos definido una función constructor, así:</p> + +<pre class="brush: js notranslate">function Persona(nombre, apellido, edad, genero, intereses) { + + // definiendo de propiedades y métodos + this.first = first; + this.last = last; +//... +} +</pre> + +<p>Entonces hemos creado una instancia de un objeto como este:</p> + +<pre class="brush: js notranslate">var person1 = new Persona('Bob', 'Smith', 32, 'hombre', ['music', 'skiing']);</pre> + +<p>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:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13853/object-available-members.png" style="display: block; margin: 0 auto;"></p> + +<p>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.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13891/MDN-Graphics-person-person-object-2.png" style="display: block; height: 150px; margin: 0px auto; width: 700px;"></p> + +<p>Entonces, ¿qué sucede si llama a un método en <code>person1</code>, que está definido en <code>Object</code>? Por ejemplo:</p> + +<pre class="brush: js notranslate">person1.valueOf()</pre> + +<p>Este método <a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">valueOf()</a> simplemente retornará el valor del objeto sobre el que se llama - ¡pruébalo y verás! En este caso, lo que pasa es que:</p> + +<ul> + <li>El navegador comprueba inicialmente si el objeto person1 tiene un método valueOf() disponible en él.</li> + <li>Si no lo hace, entonces el navegador comprueba si el objeto prototipo del objeto person1 (el prototipo del constructor de Persona()) tiene un método valueOf() disponible en él.</li> + <li>Si tampoco lo hace, entonces el navegador comprueba si el objeto prototipo del objeto prototipo del constructor Persona() (Objeto() prototipo del objeto prototipo del constructor) tiene un método valueOf() disponible en él. Lo hace, así que es llamado, y todo funciona!</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: 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.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: 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")}}).</p> + +<p>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!</p> + +<p>Desde ECMAScript 2015 se puede acceder indirectamente al objeto prototipo de un objeto mediante Object.getPrototypeOf(obj).</p> +</div> + +<h2 id="La_propiedad_prototype_Donde_se_definen_los_miembros_hereditarios">La propiedad prototype: Donde se definen los miembros hereditarios</h2> + +<p>Entonces, ¿dónde se definen las propiedades y métodos heredados? Si miras la página de referencia de <code>Object</code>, 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 <code>person1</code>. Algunos son heredados y otros no, ¿por qué?</p> + +<p>La respuesta es que los heredados son los que están definidos en la propiedad <code>prototype</code> (podría llamarse subespacio de nombres), es decir, los que empiezan con <code>Object.prototype</code>, y no los que empiezan sólo con <code>Object</code>. 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.</p> + +<p>Así que <code>Object.prototype.watch()</code>, <code>Object.prototype.valueOf()</code>, etc., están disponibles para cualquier tipo de objeto que herede de <code>Object.prototype</code>, incluyendo nuevas instancias de objeto creadas desde el constructor.</p> + +<p><code><a href="https://wiki.developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/is">Object.is()</a></code>, <code><a href="https://wiki.developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys">Object.keys()</a></code>, 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().</p> + +<div class="note"> +<p><strong>Nota</strong>: 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.</p> +</div> + +<ol> + <li>Puede comprobar las propiedades de los prototipos existentes - vuelva a nuestro ejemplo anterior e intente introducir lo siguiente en la consola JavaScript: + <pre class="brush: js notranslate">Person.prototype</pre> + </li> + <li>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: + <pre class="brush: js notranslate">Object.prototype</pre> + </li> +</ol> + +<p>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.</p> + +<p>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:</p> + +<pre class="brush: js notranslate">var myString = 'Esto es mi String.';</pre> + +<p><code>myString</code> inmediatamente tiene una serie de métodos útiles disponibles en él, como <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split">split()</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf">indexOf()</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a></code>, etc.</p> + +<div class="warning"> +<p><strong>Importante</strong>: La propiedad <code>prototype </code>es una de las partes más confusamente nombradas de JavaScript - podría pensarse que <code>this </code>apunta al objeto prototipo del objeto actual, pero no lo hace (es un objeto interno al que puede accederse mediante <code>__proto__</code>, ¿recuerda?). en su lugar, <code>prototype </code>es una propiedad que contiene un objeto en el que se definen los miembros que se desea que se hereden.</p> +</div> + +<h2 id="Revisando_create">Revisando create()</h2> + +<p>Anteriormente mostramos cómo <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code> crea una nueva instancia de objeto.</p> + +<ol> + <li>Por ejemplo, pruebe esto en la consola JavaScript de su ejemplo anterior: + <pre class="brush: js notranslate">var person2 = Object.create(person1);</pre> + </li> + <li>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: + <pre class="brush: js notranslate">person2.__proto__</pre> + </li> +</ol> + +<p>Esto devolverá el objeto Persona.</p> + +<h2 id="La_propiedad_constructor">La propiedad constructor</h2> + +<p>Cada función de constructor tiene una propiedad <code>prototype</code> cuyo valor es un objeto que contiene una propiedad <code>constructor</code>. Esta propiedad <code>constructor </code>apunta a la función constructor original.</p> + +<p>Como verá en la siguiente sección, las propiedades definidas en la propiedad Person.prototype (o en general en la propiedad <code>prototype</code> 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 <code>Person()</code>. Por lo tanto, la propiedad del constructor también está disponible tanto para los objetos <code>person1 </code>como para los objetos <code>person2</code>.</p> + +<ol> + <li>Por ejemplo, pruebe estos comandos en la consola: + <pre class="brush: js notranslate">person1.constructor +person2.constructor</pre> + + <p>Ambos deberían devolver el constructor <code>Person()</code>, ya que contienen la definición original de esas instancias.</p> + + <p>Un truco interesante es que se puede añadir paréntesis al final de la propiedad <code>constructor</code> (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 <code>new</code> para especificar que se quiere usar la función como un constructor.</p> + </li> + <li>Inténtese esto en la consola: + <pre class="brush: js notranslate">let person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);</pre> + </li> + <li>Ahora intente acceder a las características del nuevo objeto, como: + <pre class="brush: js notranslate">person3.name.first +person3.age +person3.bio()</pre> + </li> +</ol> + +<p>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.</p> + +<p>La propiedad <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code> 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:</p> + +<pre class="brush: js notranslate">instanceName.constructor.name</pre> + +<p>Intente esto, por ejemplo:</p> + +<pre class="brush: js notranslate">person1.constructor.name +</pre> + +<div class="note"> +<p><strong>Nota</strong>: El valor de <code>constructor.name</code> puede cambiar (debido a herencia de prototipos, binding, preprocesores, transpiladores, etc.), por lo que para ejemplos más complejos es preferible usar el operador <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/instanceof">instanceof</a></code> en su lugar. </p> +</div> + +<ol> +</ol> + +<h2 id="Modificando_prototipos">Modificando prototipos</h2> + +<p>Vamos a echar un vistzo a un ejemplo para modificar la propiedad <code>prototype</code> 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).</p> + +<ol> + <li>Regresemos a nuestro ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> y creemos una copia local del <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">código fuente</a>. Debajo del código JavaScript existente, agrega el siguiente código, el cuál añade un nuevo método a la propiedad <code>prototype</code> del constructor: + + <pre class="brush: js notranslate">Person.prototype.farewell = function() { + alert(this.name.first + ' has left the building. Bye for now!'); +};</pre> + </li> + <li>Guarda el código y abre la página en el navegador, e ingresa lo siguiente en la entrada de texto. + <pre class="brush: js notranslate">person1.farewell();</pre> + </li> +</ol> + +<p>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</p> + +<p>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.</p> + +<pre class="brush: js notranslate">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!'); +};.</pre> + +<p>Pero el método <code>farewell()</code> aún se encuentra disponible en la instancia <code>person1</code>, su funcionalidad disponible ha sido automáticamente actualizada incluído en método recién definido <code>farewell()</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estás teniendo problemas haciendo funcionar este ejemplo, echa un vistazo en nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html">oojs-class-prototype.html</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html">míralo ejecutarse en tiempo real</a>).</p> +</div> + +<p>Raramente verás propiedades definidas en la propiedad <code>prototype</code>, ya no son muy flexibles cuando son definidas de esta forma. Por ejemplo, puedes añadir una propiedad como esta:</p> + +<pre class="brush: js notranslate">Person.prototype.fullName = 'Bob Smith'; +</pre> + +<p>Esto no es muy flexible, ya que la persona podría no llamarse así. Sería mucho mejor construir <code>fullname</code> desde <code>name.first</code> y <code>name.last</code>.</p> + +<pre class="brush: js notranslate">Person.prototype.fullName = this.name.first + ' ' + this.name.last; +</pre> + +<p>Sin embargo esto no funciona, ya que <code>this</code> estará referenciando al scope global en este caso, no al scope de la función. Llamar esta propiedad retornaría <code>undefined undefined</code>. 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.</p> + +<p>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:</p> + +<pre class="brush: js notranslate">// 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. +</pre> + +<p>Este patrón puede verse en acción en el ejemplo de la <a href="https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js">aplicación de planificador escolar</a> de Piotr Zalewa.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>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.</p> + +<p>En el proximos articulo vamos a ver como puedes implementar la herencia de funcionalidades entre dos de tus propios objetos personalizados.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> |