Comience con Node: una introducción a las API, HTTP y JavaScript ES6+

 

 

 

  • Planificación y proceso del sistema de diseño, con Nathan Curtis
  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX

  • Índice
    1. ¿Qué es Node.js?
    2. Bloqueo/No bloqueo y síncrono/asíncrono
    3. Funciones de devolución de llamada
    4. Promesas sobre devoluciones de llamadas
    5. ES6 constante frente a let
    6. Funciones de flecha ES6
    7. Clases ES6

    Una introducción al proceso de desarrollo de aplicaciones web backend: analiza las características innovadoras de JavaScript ES6+, el protocolo de transferencia de hipertexto, el trabajo con API y JSON y el uso de Node.js para crear backends rápidos y escalables.

     

    Probablemente haya oído hablar de Node.js como un "tiempo de ejecución de JavaScript asíncrono construido sobre el motor JavaScript V8 de Chrome" y que "utiliza un modelo de E/S sin bloqueo y controlado por eventos que lo hace liviano y eficiente". Pero para algunos, esa no es la mejor de las explicaciones.

    ¿Qué es Node en primer lugar? ¿Qué significa exactamente que Node sea "asincrónico" y en qué se diferencia de "sincrónico"? ¿Cuál es el significado de “controlado por eventos” y “sin bloqueo” y cómo encaja Node en el panorama más amplio de aplicaciones, redes de Internet y servidores?

    Intentaremos responder todas estas preguntas y más a lo largo de esta serie a medida que analizamos en profundidad el funcionamiento interno de Node, aprendemos sobre el Protocolo de transferencia de hipertexto, las API y JSON, y creamos nuestra propia API Bookshelf utilizando MongoDB, Express, Lodash, Mocha y Manillar.

    ¿Qué es Node.js?

    Node es sólo un entorno, o tiempo de ejecución, dentro del cual ejecutar JavaScript normal (con pequeñas diferencias) fuera del navegador. Podemos usarlo para crear aplicaciones de escritorio (con marcos como Electron), escribir servidores web o de aplicaciones, y más.

    Bloqueo/No bloqueo y síncrono/asíncrono

    Supongamos que estamos realizando una llamada a una base de datos para recuperar propiedades de un usuario. Esa llamada llevará tiempo, y si la solicitud está "bloqueando", eso significa que bloqueará la ejecución de nuestro programa hasta que se complete la llamada. En este caso, hicimos una solicitud "sincrónica" ya que terminó bloqueando el hilo.

     

    Entonces, una operación sincrónica bloquea un proceso o hilo hasta que se completa esa operación, dejando el hilo en un "estado de espera". Una operación asincrónica , por otro lado, no es bloqueante . Permite que la ejecución del subproceso continúe independientemente del tiempo que tarde en completarse la operación o del resultado con el que se complete, y ninguna parte del subproceso cae en estado de espera en ningún momento.

    Veamos otro ejemplo de una llamada sincrónica que bloquea un hilo. Supongamos que estamos creando una aplicación que compara los resultados de dos API meteorológicas para encontrar su diferencia porcentual en temperatura. De forma bloqueante, realizamos una llamada a Weather API One y esperamos el resultado. Una vez que obtenemos un resultado, llamamos a Weather API Two y esperamos su resultado. No se preocupe en este punto si no está familiarizado con las API. Los cubriremos en una próxima sección. Por ahora, piense en una API como el medio a través del cual dos computadoras pueden comunicarse entre sí.

    Progresión temporal de operaciones de bloqueo sincrónico ( vista previa grande )

    Permítanme señalar que es importante reconocer que no todas las llamadas sincrónicas necesariamente bloquean. Si una operación síncrona puede completarse sin bloquear el subproceso o causar un estado de espera, no fue bloqueante. La mayoría de las veces, las llamadas sincrónicas se bloquearán y el tiempo que tarden en completarse dependerá de una variedad de factores, como la velocidad de los servidores de la API, la velocidad de descarga de la conexión a Internet del usuario final, etc.

    En el caso de la imagen de arriba, tuvimos que esperar bastante para recuperar los primeros resultados de API One. A partir de entonces, tuvimos que esperar el mismo tiempo para obtener una respuesta de API Two. Mientras esperaba ambas respuestas, el usuario notaría que nuestra aplicación se bloquea (la interfaz de usuario literalmente se bloquearía) y eso sería malo para la experiencia del usuario.

    En el caso de una llamada sin bloqueo, tendríamos algo como esto:

    Progresión temporal de operaciones asincrónicas sin bloqueo ( vista previa grande )

    Puede ver claramente cuánto más rápido concluimos la ejecución. En lugar de esperar a API Uno y luego esperar a API Dos, podríamos esperar a que ambos se completen al mismo tiempo y lograr nuestros resultados casi un 50% más rápido. Observe que una vez que llamamos a API One y comenzamos a esperar su respuesta, también llamamos a API Two y comenzamos a esperar su respuesta al mismo tiempo que One.

    En este punto, antes de pasar a ejemplos más concretos y tangibles, es importante mencionar que, para facilitar, el término "Sincrónico" generalmente se abrevia a "Sincronizar", y el término "Asincrónico" generalmente se abrevia a "Async". Verá esta notación utilizada en los nombres de métodos/funciones.

    Funciones de devolución de llamada

    Quizás se pregunte: "si podemos manejar una llamada de forma asincrónica, ¿cómo sabemos cuándo finaliza esa llamada y tenemos una respuesta?" Generalmente, pasamos como argumento a nuestro método asíncrono una función de devolución de llamada, y ese método "devolverá la llamada" a esa función más adelante con una respuesta. Estoy usando funciones de ES5 aquí, pero las actualizaremos a los estándares de ES6 más adelante.

     

    function asyncAddFunction(a, b, callback) { callback(a + b); //This callback is the one passed in to the function call below.}asyncAddFunction(2, 4, function(sum) { //Here we have the sum, 2 + 4 = 6.});

    Esta función se denomina "función de orden superior", ya que toma una función (nuestra devolución de llamada) como argumento. Alternativamente, una función de devolución de llamada podría tomar un objeto de error y un objeto de respuesta como argumentos y presentarlos cuando se complete la función asíncrona. Veremos esto más adelante con Express. Cuando llamamos asyncAddFunction(...), notará que proporcionamos una función de devolución de llamada para el parámetro de devolución de llamada desde la definición del método. Esta función es una función anónima (no tiene nombre) y está escrita utilizando la sintaxis de expresión . La definición del método, por otro lado, es una declaración de función. No es anónimo porque en realidad tiene un nombre (que es "asyncAddFunction").

    Algunos pueden notar confusión ya que, en la definición del método, proporcionamos un nombre, que es "devolución de llamada". Sin embargo, la función anónima pasada como tercer parámetro asyncAddFunction(...)no conoce el nombre y, por lo tanto, permanece anónima. Tampoco podemos ejecutar esa función en un momento posterior por nombre, tendríamos que volver a realizar la función de llamada asíncrona para activarla.

    Como ejemplo de llamada sincrónica, podemos usar el readFileSync(...)método Node.js. Nuevamente, pasaremos a ES6+ más adelante.

    var fs = require('fs');var data = fs.readFileSync('/example.txt'); // The thread will be blocked here until complete.

    Si estuviéramos haciendo esto de forma asincrónica, pasaríamos una función de devolución de llamada que se activaría cuando se completara la operación asincrónica.

    var fs = require('fs');var data = fs.readFile('/example.txt', function(err, data) { //Move on, this will fire when ready. if(err) return console.log('Error: ', err); console.log('Data: ', data); // Assume var data is defined above.});// Keep executing below, don’t wait on the data.

    Si nunca returnantes lo ha visto usado de esa manera, solo estamos diciendo que detenga la ejecución de la función para no imprimir el objeto de datos si el objeto de error está definido. También podríamos haber incluido la declaración de registro en una elsecláusula.

    Al igual que nuestro asyncAddFunction(...), el código detrás de la fs.readFile(...)función sería algo como:

    function readFile(path, callback) { // Behind the scenes code to read a file stream. // The data variable is defined up here. callback(undefined, data); //Or, callback(err, undefined);}

    Permítanos ver una última implementación de una llamada a función asíncrona. Esto ayudará a solidificar la idea de que las funciones de devolución de llamada se activen en un momento posterior y nos ayudará a comprender la ejecución de un programa Node.js típico.

     

    setTimeout(function() { // ...}, 1000);

    El setTimeout(...)método toma una función de devolución de llamada para el primer parámetro que se activará después de que haya ocurrido la cantidad de milisegundos especificada como segundo argumento.

    Veamos un ejemplo más complejo:

    console.log('Initiated program.');setTimeout(function() { console.log('3000 ms (3 sec) have passed.');}, 3000);setTimeout(function() { console.log('0 ms (0 sec) have passed.');}, 0);setTimeout(function() { console.log('1000 ms (1 sec) has passed.');}, 1000);console.log('Terminated program');

    La salida que recibimos es:

    Initiated program.Terminated program.0 ms (0 sec) have passed.1000 ms (1 sec) has passed.3000 ms (3 sec) have passed.

    Puede ver que la primera declaración de registro se ejecuta como se esperaba. Instantáneamente, la última declaración de registro se imprime en la pantalla, ya que eso sucede antes de que se superen los 0 segundos después del segundo setTimeout(...). Inmediatamente después, se ejecutan el segundo, tercer y primer setTimeout(...)método.

    Si Node.js no fuera de bloqueo, veríamos la primera declaración de registro, esperaríamos 3 segundos para ver la siguiente, veríamos instantáneamente la tercera (la de 0 segundos setTimeout(...), y luego tendríamos que esperar un segundo más para ver las dos últimas). declaraciones de registro. La naturaleza sin bloqueo de Node hace que todos los temporizadores comiencen a contar desde el momento en que se ejecuta el programa, en lugar del orden en el que se escriben. Es posible que desee consultar las API de Node, la pila de llamadas y el bucle de eventos. para obtener más información sobre cómo funciona Node bajo el capó.

    Es importante tener en cuenta que el hecho de que vea una función de devolución de llamada no significa necesariamente que haya una llamada asincrónica en el código. Llamamos al asyncAddFunction(…)método anterior "async" porque asumimos que la operación tarda tiempo en completarse, como hacer una llamada a un servidor. En realidad, el proceso de sumar dos números no es asíncrono, por lo que en realidad sería un ejemplo de uso de una función de devolución de llamada de una manera que en realidad no bloquea el hilo.

    Promesas sobre devoluciones de llamadas

    Las devoluciones de llamada pueden volverse confusas rápidamente en JavaScript, especialmente las devoluciones de llamada múltiples anidadas. Estamos familiarizados con pasar una devolución de llamada como argumento a una función, pero las promesas nos permiten agregar o adjuntar una devolución de llamada a un objeto devuelto por una función. Esto nos permitiría manejar múltiples llamadas asíncronas de una manera más elegante.

    Como ejemplo, supongamos que estamos realizando una llamada a la API y nuestra función, cuyo nombre no es tan exclusivo " makeAPICall(...)", toma una URL y una devolución de llamada.

    Nuestra función, makeAPICall(...), se definiría como

    function makeAPICall(path, callback) { // Attempt to make API call to path argument. // ... callback(undefined, res); // Or, callback(err, undefined); depending upon the API’s response.}

    y lo llamaríamos con:

     

    makeAPICall('/example', function(err1, res1) { if(err1) return console.log('Error: ', err1); // ...});

    Si quisiéramos realizar otra llamada API usando la respuesta de la primera, tendríamos que anidar ambas devoluciones de llamada. Supongamos que necesito inyectar la userNamepropiedad del res1objeto en la ruta de la segunda llamada API. Tendríamos:

    makeAPICall('/example', function(err1, res1) { if(err1) return console.log('Error: ', err1); makeAPICall('/newExample/' + res1.userName, function(err2, res2) { if(err2) return console.log('Error: ', err2); console.log(res2); });});

    Nota : El método ES6+ para inyectar la res1.userNamepropiedad en lugar de la concatenación de cadenas sería utilizar "Cadenas de plantilla". De esa manera, en lugar de encapsular nuestra cadena entre comillas ( 'o "), usaríamos comillas invertidas ( `). ubicado debajo de la tecla Escape en su teclado. Luego, usaríamos la notación ${}para incrustar cualquier expresión JS entre corchetes. Al final, nuestro camino anterior sería: /newExample/${res.UserName}, entre comillas invertidas.

    Está claro que este método de anidar devoluciones de llamadas puede volverse bastante poco elegante rápidamente, lo que se conoce como la “Pirámide de la perdición de JavaScript”. Si usáramos promesas en lugar de devoluciones de llamadas, podríamos refactorizar nuestro código del primer ejemplo como tal:

    makeAPICall('/example').then(function(res) { // Success callback. // ...}, function(err) { // Failure callback. console.log('Error:', err);});

    El primer argumento de la then()función es nuestra devolución de llamada exitosa y el segundo argumento es nuestra devolución de llamada fallida. Alternativamente, podríamos perder el segundo argumento .then()y llamar .catch()en su lugar. Los argumentos to .then()son opcionales y llamar .catch()sería equivalente a .then(successCallback, null).

    Usando .catch(), tenemos:

    makeAPICall('/example').then(function(res) { // Success callback. // ...}).catch(function(err) { // Failure Callback console.log('Error: ', err);});

    También podemos reestructurar esto para facilitar la lectura: Mejores Opiniones y reviews

    makeAPICall('/example') .then(function(res) { // ... }) .catch(function(err) { console.log('Error: ', err); });

    Es importante tener en cuenta que no podemos simplemente agregar una .then()llamada a cualquier función y esperar que funcione. La función que estamos llamando tiene que devolver una promesa, una promesa que se activará .then()cuando se complete la operación asíncrona. En este caso, makeAPICall(...)hará lo suyo, disparando el then()bloque o el catch()bloque cuando esté completo.

    Para makeAPICall(...)devolver una Promesa, asignamos una función a una variable, donde esa función es el constructor de la Promesa. Las promesas pueden cumplirse o rechazarse , donde cumplida significa que la acción relacionada con la promesa se completó con éxito y rechazada significa lo contrario. Una vez que la promesa se cumple o se rechaza, decimos que se ha liquidado y, mientras esperamos que se liquide, tal vez durante una llamada asíncrona, decimos que la promesa está pendiente .

     

    El constructor de Promise toma una función de devolución de llamada como argumento, que recibe dos parámetros, resolvey reject, que llamaremos en un momento posterior para activar la devolución de llamada exitosa en .then(), o la .then()devolución de llamada fallida, o .catch(), si se proporciona.

    A continuación se muestra un ejemplo de cómo se ve esto:

    var examplePromise = new Promise(function(resolve, reject) { // Do whatever we are going to do and then make the appropiate call below: resolve('Happy!'); // — Everything worked. reject('Sad!'); // — We noticed that something went wrong.}):

    Entonces, podemos usar:

    examplePromise.then(/* Both callback functions in here */);// Or, the success callback in .then() and the failure callback in .catch().

    Tenga en cuenta, sin embargo, que eso examplePromiseno puede aceptar ningún argumento. Eso frustra el propósito, por lo que podemos devolver una promesa en su lugar.

    function makeAPICall(path) { return new Promise(function(resolve, reject) { // Make our async API call here. if (/* All is good */) return resolve(res); //res is the response, would be defined above. else return reject(err); //err is error, would be defined above. });}

    Las promesas realmente brillan para mejorar la estructura y, posteriormente, la elegancia de nuestro código con el concepto de “Promise Chaining”. Esto nos permitiría devolver una nueva Promesa dentro de una .then()cláusula, de modo que podríamos adjuntar una segunda promesa .then()a partir de entonces, lo que activaría la devolución de llamada apropiada desde la segunda promesa.

    Al refactorizar nuestra llamada de URL de API múltiple anterior con Promesas, obtenemos:

    makeAPICall('/example').then(function(res) { // First response callback. Fires on success to '/example' call. return makeAPICall(`/newExample/${res.UserName}`); // Returning new call allows for Promise Chaining.}, function(err) { // First failure callback. Fires if there is a failure calling with '/example'. console.log('Error:', err);}).then(function(res) { // Second response callback. Fires on success to returned '/newExample/...' call. console.log(res);}, function(err) { // Second failure callback. Fire if there is a failure calling with '/newExample/...' console.log('Error:', err);});

    Observe que primero llamamos makeAPICall('/example'). Eso devuelve una promesa, por lo que adjuntamos un archivo .then(). Dentro de eso then(), devolvemos una nueva llamada a makeAPICall(...), que, en sí misma, como se vio anteriormente, devuelve una promesa, lo que nos permite encadenar una nueva .then()después de la primera.

    Como arriba, podemos reestructurar esto para facilitar la lectura y eliminar las devoluciones de llamada de falla para una catch()cláusula general genérica. Luego, podemos seguir el principio DRY (No te repitas) y solo tenemos que implementar el manejo de errores una vez.

     

    makeAPICall('/example') .then(function(res) { // Like earlier, fires with success and response from '/example'. return makeAPICall(`/newExample/${res.UserName}`); // Returning here lets us chain on a new .then(). }) .then(function(res) { // Like earlier, fires with success and response from '/newExample'. console.log(res); }) .catch(function(err) { // Generic catch all method. Fires if there is an err with either earlier call. console.log('Error: ', err); });

    Tenga en cuenta que las devoluciones de llamada de éxito y fracaso .then()solo se activan para el estado de la Promesa individual que .then()corresponde. El catchbloque, sin embargo, detectará cualquier error que se active en cualquiera de los .then()s.

    ES6 constante frente a let

    A lo largo de todos nuestros ejemplos, hemos estado empleando funciones de ES5 y la varpalabra clave antigua. Si bien hoy en día todavía se ejecutan millones de líneas de código empleando esos métodos ES5, es útil actualizar a los estándares actuales de ES6+ y refactorizaremos parte de nuestro código anterior. Empecemos con consty let.

    Es posible que esté acostumbrado a declarar una variable con la varpalabra clave:

    var pi = 3.14;

    Con los estándares ES6+, podríamos lograrlo.

    let pi = 3.14;

    o

    const pi = 3.14;

    donde constsignifica "constante", un valor al que no se puede reasignar más adelante. (A excepción de las propiedades de los objetos, las cubriremos pronto. Además, las variables declaradas noconst son inmutables, solo la referencia a la variable lo es).

    En JavaScript antiguo, bloquee ámbitos, como los de if, while, {}. for, etc. no afectó varde ninguna manera, y esto es bastante diferente a lenguajes de tipo más estático como Java o C++. Es decir, el alcance de vares toda la función circundante, y podría ser global (si se coloca fuera de una función) o local (si se coloca dentro de una función). Para demostrar esto, vea el siguiente ejemplo:

    function myFunction() { var num = 5; console.log(num); // 5 console.log('--'); for(var i = 0; i 10; i++) { var num = i; console.log(num); //num becomes 0 — 9 } console.log('--'); console.log(num); // 9 console.log(i); // 10}myFunction();

    Producción:

    5---01 2 3 ... 7 8 9---910

    Lo importante a tener en cuenta aquí es que definir un nuevo var numdentro del foralcance afectó directamente el var numexterior y por encima del for. Esto se debe a que varel alcance de ' es siempre el de la función adjunta y no un bloque.

    Nuevamente, de manera predeterminada, el valor var iinterno es el alcance, por lo que podemos acceder fuera del bucle y obtener 10.for()myFunctioni

    En términos de asignar valores a las variables, letes equivalente a var, es solo que lettiene alcance de bloque, por lo que las anomalías que ocurrieron varanteriormente no sucederán.

     

    function myFunction() { let num = 5; console.log(num); // 5 for(let i = 0; i 10; i++) { let num = i; console.log('--'); console.log(num); // num becomes 0 — 9 } console.log('--'); console.log(num); // 5 console.log(i); // undefined, ReferenceError}

    Al observar la constpalabra clave, puede ver que obtenemos un error si intentamos reasignarla:

    const c = 299792458; // Fact: The constant "c" is the speed of light in a vacuum in meters per second.c = 10; // TypeError: Assignment to constant variable.

    Las cosas se vuelven interesantes cuando asignamos una constvariable a un objeto:

    const myObject = { name: 'Jane Doe'};// This is illegal: TypeError: Assignment to constant variable.myObject = { name: 'John Doe'};// This is legal. console.log(myObject.name) - John DoemyObject.name = 'John Doe';

    Como puede ver, solo la referencia en la memoria al objeto asignado a un constobjeto es inmutable, no el valor en sí.

    Funciones de flecha ES6

    Es posible que esté acostumbrado a crear una función como esta:

    function printHelloWorld() { console.log('Hello, World!');}

    Con funciones de flecha, eso se convertiría en:

    const printHelloWorld = () = { console.log('Hello, World!');};

    Supongamos que tenemos una función simple que devuelve el cuadrado de un número:

    const squareNumber = (x) = { return x * x;}squareNumber(5); // We can call an arrow function like an ES5 functions. Returns 25.

    Puede ver que, al igual que con las funciones de ES5, podemos aceptar argumentos entre paréntesis, podemos usar declaraciones de retorno normales y podemos llamar a la función como cualquier otra.

    Es importante tener en cuenta que, si bien se requieren paréntesis si nuestra función no toma argumentos (como printHelloWorld()arriba), podemos eliminar los paréntesis si solo toma uno, por lo que nuestra squareNumber()definición de método anterior se puede reescribir como:

    const squareNumber = x = { // Notice we have dropped the parentheses for we only take in one argument. return x * x;}

    Si elige encapsular un solo argumento entre paréntesis o no es una cuestión de gusto personal, y probablemente verá que los desarrolladores utilizan ambos métodos.

    Finalmente, si solo queremos devolver implícitamente una expresión, como squareNumber(...)arriba, podemos alinear la declaración de retorno con la firma del método:

    const squareNumber = x = x * x;

    Eso es,

    const test = (a, b, c) = expression

    es lo mismo que

    const test = (a, b, c) = { return expression }

    Tenga en cuenta que cuando se utiliza la taquigrafía anterior para devolver implícitamente un objeto, las cosas se vuelven oscuras. ¿Qué impide que JavaScript crea que los corchetes dentro de los cuales debemos encapsular nuestro objeto no son el cuerpo de nuestra función? Para solucionar esto, envolvemos los corchetes del objeto entre paréntesis. Esto le permite explícitamente a JavaScript saber que efectivamente estamos devolviendo un objeto y que no solo estamos definiendo un cuerpo.

     

    const test = () = ({ pi: 3.14 }); // Spaces between brackets are a formality to make the code look cleaner.

    Para ayudar a solidificar el concepto de funciones de ES6, refactorizaremos parte de nuestro código anterior, lo que nos permitirá comparar las diferencias entre ambas notaciones.

    asyncAddFunction(...), desde arriba, podría refactorizarse desde:

    function asyncAddFunction(a, b, callback){ callback(a + b);}

    a:

    const aysncAddFunction = (a, b, callback) = { callback(a + b);};

    o incluso a:

    const aysncAddFunction = (a, b, callback) = callback(a + b); // This will return callback(a + b).

    Al llamar a la función, podríamos pasar una función de flecha para la devolución de llamada:

    asyncAddFunction(10, 12, sum = { // No parentheses because we only take one argument. console.log(sum);}

    Está claro cómo este método mejora la legibilidad del código. Para mostrarle solo un caso, podemos tomar nuestro antiguo ejemplo anterior basado en ES5 Promise y refactorizarlo para usar funciones de flecha.

    makeAPICall('/example') .then(res = makeAPICall(`/newExample/${res.UserName}`)) .then(res = console.log(res)) .catch(err = console.log('Error: ', err));

    Ahora bien, hay algunas advertencias con las funciones de flecha. Por un lado, no vinculan una thispalabra clave. Supongamos que tengo el siguiente objeto:

    const Person = { name: 'John Doe', greeting: () = { console.log(`Hi. My name is ${this.name}.`); }}

    Es posible que espere que una llamada le Person.greeting()responda “Hola. Mi nombre es John Doe”. En lugar de eso, recibimos: “Hola. Mi nombre no está definido”. Esto se debe a que las funciones de flecha no tienen un this, por lo que intentar usar thisdentro de una función de flecha tiene como valor predeterminado el thisalcance circundante, y el alcance circundante del Personobjeto es window, en el navegador o module.exportsen Node.

    Para probar esto, si usamos el mismo objeto nuevamente, pero establecemos la namepropiedad del global thisen algo como 'Jane Doe', entonces this.nameen la función de flecha devuelve 'Jane Doe', porque el global thisestá dentro del alcance adjunto, o es el padre del Personobjeto.

    this.name = 'Jane Doe';const Person = { name: 'John Doe', greeting: () = { console.log(`Hi. My name is ${this.name}.`); }}Person.greeting(); // Hi. My name is Jane Doe

    Esto se conoce como 'alcance léxico', y podemos solucionarlo usando la llamada 'sintaxis corta', que es donde perdemos los dos puntos y la flecha para refactorizar nuestro objeto como tal:

    const Person = { name: 'John Doe', greeting() { console.log(`Hi. My name is ${this.name}.`); }}Person.greeting() //Hi. My name is John Doe.

    Clases ES6

    Si bien JavaScript nunca admitió clases, siempre puedes emularlas con objetos como el anterior. EcmaScript 6 proporciona soporte para clases que utilizan las palabras clave classy new:

    class Person { constructor(name) { this.name = name; } greeting() { console.log(`Hi. My name is ${this.name}.`); }}const person = new Person(‘John’);person.greeting(); // Hi. My name is John.

    La función constructora se llama automáticamente cuando se usa la newpalabra clave, a la que podemos pasar argumentos para configurar inicialmente el objeto. Esto debería resultarle familiar a cualquier lector que tenga experiencia con lenguajes de programación orientados a objetos de tipo más estático, como Java, C++ y C#.

    Sin entrar en demasiados detalles sobre los conceptos de programación orientada a objetos, otro paradigma de este tipo es la "herencia", que consiste en permitir que una clase herede de otra. Una clase llamada Car






    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Comience con Node: una introducción a las API, HTTP y JavaScript ES6+

    Comience con Node: una introducción a las API, HTTP y JavaScript ES6+

    Planificación y proceso del sistema de diseño, con Nathan Curtis Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX Índice

    programar

    es

    https://aprendeprogramando.es/static/images/programar-comience-con-node-una-introduccion-a-las-api-971-0.jpg

    2024-05-20

     

    Comience con Node: una introducción a las API, HTTP y JavaScript ES6+
    Comience con Node: una introducción a las API, HTTP y JavaScript ES6+

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20