Capítulo 1. Introducción a JavaScript

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

JavaScript es el lenguaje de programación de la web. La inmensa mayoría de los sitios web utilizan JavaScript, y todos los navegadores web modernos -en ordenadores de sobremesa, tabletas y teléfonos- incluyen intérpretes de JavaScript, lo que hace de JavaScript el lenguaje de programación más implementado de la historia. En la última década, Node.js ha permitido programar en JavaScript fuera de los navegadores web, y el espectacular éxito de Node significa que JavaScript es ahora también el lenguaje de programación más utilizado entre los desarrolladores de software. Tanto si empiezas desde cero como si ya utilizas JavaScript profesionalmente, este libro te ayudará a dominar el lenguaje.

Si ya estás familiarizado con otros lenguajes de programación, puede ayudarte saber que JavaScript es un lenguaje de programación interpretado, dinámico y de alto nivel, que se adapta bien a los estilos de programación funcional y orientada a objetos. Las variables de JavaScript no están tipadas. Su sintaxis está vagamente basada en Java, pero por lo demás no tienen nada que ver. JavaScript deriva sus funciones de primera clase de Scheme y su herencia basada en prototipos del poco conocido lenguaje Self. Pero no necesitas conocer ninguno de esos lenguajes, ni estar familiarizado con esos términos, para utilizar este libro y aprender JavaScript.

El nombre "JavaScript" es bastante engañoso. Salvo por un parecido sintáctico superficial, JavaScript es completamente diferente del lenguaje de programación Java. Y hace tiempo que JavaScript ha superado sus raíces de lenguaje de scripting para convertirse en un lenguaje robusto y eficiente de propósito general, adecuado para la ingeniería de software seria y los proyectos con enormes bases de código.

Para ser útil, todo lenguaje debe tener una plataforma, o biblioteca estándar, para realizar cosas como la entrada y salida básicas. El núcleo del lenguaje JavaScript define una API mínima para trabajar con números, texto, matrices, conjuntos, mapas, etc., pero no incluye ninguna funcionalidad de entrada o salida. La entrada y la salida (así como las funciones más sofisticadas, como la conexión en red, el almacenamiento y los gráficos) son responsabilidad del "entorno anfitrión" en el que está incrustado JavaScript.

El entorno anfitrión original para JavaScript fue un navegador web, y éste sigue siendo el entorno de ejecución más común para el código JavaScript. El entorno del navegador web permite que el código JavaScript obtenga información del ratón y el teclado del usuario y mediante solicitudes HTTP. Y permite que el código JavaScript muestre la salida al usuario con HTML y CSS.

Desde 2010, existe otro entorno anfitrión para el código JavaScript. En lugar de limitar JavaScript a trabajar con las API proporcionadas por un navegador web, Node da a JavaScript acceso a todo el sistema operativo, permitiendo a los programas JavaScript leer y escribir archivos, enviar y recibir datos a través de la red, y hacer y servir solicitudes HTTP. Node es una opción popular para implementar servidores web y también una herramienta práctica para escribir scripts de utilidades sencillas como alternativa a los scripts shell.

La mayor parte de este libro se centra en el propio lenguaje JavaScript.El Capítulo 11 documenta la biblioteca estándar de JavaScript, el Capítulo 15 presenta el entorno host del navegador web yel Capítulo 16 presenta el entorno host de Node.

Este libro trata primero los fundamentos de bajo nivel, y luego se basa en ellos para llegar a abstracciones más avanzadas y de más alto nivel. Los capítulos están pensados para leerse más o menos en orden. Pero aprender un nuevo lenguaje de programación nunca es un proceso lineal, y describir un lenguaje tampoco lo es: cada característica del lenguaje está relacionada con otras, y este libro está lleno de referencias cruzadas -a veces hacia atrás y a veces hacia delante- a material relacionado. Este capítulo introductorio hace una rápida primera pasada por el lenguaje, introduciendo características clave que facilitarán la comprensión del tratamiento en profundidad de los capítulos siguientes. Si ya eres un programador de JavaScript en activo, probablemente puedas saltarte este capítulo. (Aunque puede que te guste leer el Ejemplo 1-1 al final del capítulo antes de seguir adelante).

1.1 Explorando JavaScript

Cuando aprendes un nuevo lenguaje de programación, es importante que pruebes los ejemplos del libro, luego los modifiques y los vuelvas a probar para comprobar tu comprensión del lenguaje. Para ello, necesitas un intérprete de JavaScript.

La forma más sencilla de probar unas líneas de JavaScript es abrir las herramientas de desarrollo web en tu navegador (con F12, Ctrl-Mayúsculas-I o Comando-Opción-I) y seleccionar la pestaña Consola. A continuación, puedes escribir código y ver los resultados a medida que escribes. Las herramientas de desarrollo del navegador suelen aparecer como paneles en la parte inferior o derecha de la ventana del navegador, pero normalmente puedes separarlas como ventanas independientes (como se muestra en la Figura 1-1), lo que suele ser bastante cómodo.

js7e 0101
Figura 1-1. La consola JavaScript en las Herramientas para desarrolladores de Firefox

Otra forma de probar el código JavaScript en es descargar e instalar Node desde https://nodejs.org. Una vez instalado Node en tu sistema, sólo tienes que abrir una ventana de Terminal y escribir node para iniciar una sesión interactiva de JavaScript como ésta:

$ node
Welcome to Node.js v12.13.0.
Type ".help" for more information.
> .help
.break    Sometimes you get stuck, this gets you out
.clear    Alias for .break
.editor   Enter editor mode
.exit     Exit the repl
.help     Print this help message
.load     Load JS from a file into the REPL session
.save     Save all evaluated commands in this REPL session to a file

Press ^C to abort current expression, ^D to exit the repl
> let x = 2, y = 3;
undefined
> x + y
5
> (x === 2) && (y === 3)
true
> (x > 3) || (y < 3)
false

1.2 Hola Mundo

Cuando en estés preparado para empezar a experimentar con trozos de código más largos, puede que estos entornos interactivos línea a línea ya no sean adecuados, y probablemente prefieras escribir tu código en un editor de texto. Desde ahí, puedes copiar y pegar en la consola de JavaScript o en una sesión de Node. O puedes guardar tu código en un archivo (la extensión de nombre de archivo tradicional para el código JavaScript es .js) y luego ejecutar ese archivo de código JavaScript con Node:

$ node snippet.js

Si utilizas Node de un modo no interactivo como éste, no imprimirá automáticamente el valor de todo el código que ejecutes, así que tendrás que hacerlo tú mismo. En puedes utilizar la función console.log() para mostrar texto y otros valores de JavaScript en la ventana de tu terminal o en la consola de herramientas de desarrollador de un navegador. Así, por ejemplo, si creas un archivohola.js que contenga esta línea de código:

console.log("Hello World!");

y ejecuta el archivo con node hello.js, verás impreso el mensaje "¡Hola Mundo!

Si quieres ver ese mismo mensaje impreso en la consola JavaScript de un navegador web, crea un nuevo archivo llamado hola.html, y pon en él este texto:

<script src="hello.js"></script>

A continuación, carga hola.html en tu navegador web utilizando una URL file:// como ésta:

file:///Users/username/javascript/hello.html

Abre la ventana de herramientas de desarrollador para ver el saludo en la consola.

1.3 Un recorrido por JavaScript

Esta sección de presenta una introducción rápida, mediante ejemplos de código, al lenguaje JavaScript. Después de este capítulo introductorio, nos sumergimos en JavaScript en el nivel más bajo:El Capítulo 2 explica cosas como los comentarios de JavaScript, el punto y coma y el conjunto de caracteres Unicode.El Capítulo 3 empieza a ponerse más interesante: explica las variables de JavaScript y los valores que puedes asignar a esas variables.

Aquí tienes algunos ejemplos de código para ilustrar lo más destacado de esos dos capítulos:

// Anything following double slashes is an English-language comment.
// Read the comments carefully: they explain the JavaScript code.

// A variable is a symbolic name for a value.
// Variables are declared with the let keyword:
let x;                     // Declare a variable named x.

// Values can be assigned to variables with an = sign
x = 0;                     // Now the variable x has the value 0
x                          // => 0: A variable evaluates to its value.

// JavaScript supports several types of values
x = 1;                     // Numbers.
x = 0.01;                  // Numbers can be integers or reals.
x = "hello world";         // Strings of text in quotation marks.
x = 'JavaScript';          // Single quote marks also delimit strings.
x = true;                  // A Boolean value.
x = false;                 // The other Boolean value.
x = null;                  // Null is a special value that means "no value."
x = undefined;             // Undefined is another special value like null.

Otros dos tipos muy importantes que los programas JavaScript pueden manipular son los objetos y las matrices. Estos son los temas de los capítulos6 y 7, pero son tan importantes que los verás muchas veces antes de llegar a esos capítulos :

// JavaScript's most important datatype is the object.
// An object is a collection of name/value pairs, or a string to value map.
let book = {               // Objects are enclosed in curly braces.
    topic: "JavaScript",   // The property "topic" has value "JavaScript."
    edition: 7             // The property "edition" has value 7
};                         // The curly brace marks the end of the object.

// Access the properties of an object with . or []:
book.topic                 // => "JavaScript"
book["edition"]            // => 7: another way to access property values.
book.author = "Flanagan";  // Create new properties by assignment.
book.contents = {};        // {} is an empty object with no properties.

// Conditionally access properties with ?. (ES2020):
book.contents?.ch01?.sect1 // => undefined: book.contents has no ch01 property.

// JavaScript also supports arrays (numerically indexed lists) of values:
let primes = [2, 3, 5, 7]; // An array of 4 values, delimited with [ and ].
primes[0]                  // => 2: the first element (index 0) of the array.
primes.length              // => 4: how many elements in the array.
primes[primes.length-1]    // => 7: the last element of the array.
primes[4] = 9;             // Add a new element by assignment.
primes[4] = 11;            // Or alter an existing element by assignment.
let empty = [];            // [] is an empty array with no elements.
empty.length               // => 0

// Arrays and objects can hold other arrays and objects:
let points = [             // An array with 2 elements.
    {x: 0, y: 0},          // Each element is an object.
    {x: 1, y: 1}
];
let data = {                 // An object with 2 properties
    trial1: [[1,2], [3,4]],  // The value of each property is an array.
    trial2: [[2,3], [4,5]]   // The elements of the arrays are arrays.
};

La sintaxis de que se ilustra aquí para enumerar elementos de matrices dentro de llaves cuadradas o asignar nombres de propiedades de objetos a valores de propiedades dentro de llaves rizadas se conoce como expresión inicializadora, y es sólo uno de los temas del Capítulo 4. Una expresión es una frase de JavaScript que puede evaluarse para producir un valor. Por ejemplo, el uso de . y [] para referirse al valor de una propiedad de objeto o de un elemento de matriz es una expresión.

Una de las formas más comunes de formar expresiones en JavaScript es utilizaroperadores:

// Operators act on values (the operands) to produce a new value.
// Arithmetic operators are some of the simplest:
3 + 2                      // => 5: addition
3 - 2                      // => 1: subtraction
3 * 2                      // => 6: multiplication
3 / 2                      // => 1.5: division
points[1].x - points[0].x  // => 1: more complicated operands also work
"3" + "2"                  // => "32": + adds numbers, concatenates strings

// JavaScript defines some shorthand arithmetic operators
let count = 0;             // Define a variable
count++;                   // Increment the variable
count--;                   // Decrement the variable
count += 2;                // Add 2: same as count = count + 2;
count *= 3;                // Multiply by 3: same as count = count * 3;
count                      // => 6: variable names are expressions, too.

// Equality and relational operators test whether two values are equal,
// unequal, less than, greater than, and so on. They evaluate to true or false.
let x = 2, y = 3;          // These = signs are assignment, not equality tests
x === y                    // => false: equality
x !== y                    // => true: inequality
x < y                      // => true: less-than
x <= y                     // => true: less-than or equal
x > y                      // => false: greater-than
x >= y                     // => false: greater-than or equal
"two" === "three"          // => false: the two strings are different
"two" > "three"            // => true: "tw" is alphabetically greater than "th"
false === (x > y)          // => true: false is equal to false

// Logical operators combine or invert boolean values
(x === 2) && (y === 3)     // => true: both comparisons are true. && is AND
(x > 3) || (y < 3)         // => false: neither comparison is true. || is OR
!(x === y)                 // => true: ! inverts a boolean value

Si Las expresiones de JavaScript son como frases,las sentencias de JavaScript son como oraciones completas. Las sentencias son el tema delCapítulo 5. A grandes rasgos, una expresión es algo que calcula un valor pero no hace nada: no altera en modo alguno el estado del programa. Las sentencias, en cambio, no tienen un valor, pero sí alteran el estado. Ya has visto declaraciones de variables y sentencias de asignación. La otra amplia categoría de sentencias son las estructuras de control, como las condicionales y los bucles. Verás ejemplos más adelante, después de tratar las funciones.

Una función es un bloque de código JavaScript nombrado y parametrizado que defines una vez y puedes invocar una y otra vez. Las funciones no se tratan formalmente hasta el Capítulo 8, pero al igual que los objetos y las matrices, las verás muchas veces antes de llegar a ese capítulo. He aquí algunos ejemplos sencillos:

// Functions are parameterized blocks of JavaScript code that we can invoke.
function plus1(x) {        // Define a function named "plus1" with parameter "x"
    return x + 1;          // Return a value one larger than the value passed in
}                          // Functions are enclosed in curly braces

plus1(y)                   // => 4: y is 3, so this invocation returns 3+1

let square = function(x) { // Functions are values and can be assigned to vars
    return x * x;          // Compute the function's value
};                         // Semicolon marks the end of the assignment.

square(plus1(y))           // => 16: invoke two functions in one expression

En ES6 y posteriores, existe una sintaxis abreviada para definir funciones. Esta sintaxis concisa utiliza => para separar la lista de argumentos del cuerpo de la función, por lo que las funciones definidas de este modo se conocen comofunciones flecha. Las funciones en flecha se suelen utilizar cuando quieres pasar una función sin nombre como argumento a otra función. El código anterior tiene este aspecto cuando se reescribe para utilizar funciones flecha:

const plus1 = x => x + 1;   // The input x maps to the output x + 1
const square = x => x * x;  // The input x maps to the output x * x
plus1(y)                    // => 4: function invocation is the same
square(plus1(y))            // => 16

Cuando utilizamos funciones con objetos, obtenemos métodos:

// When functions are assigned to the properties of an object, we call
// them "methods."  All JavaScript objects (including arrays) have methods:
let a = [];                // Create an empty array
a.push(1,2,3);             // The push() method adds elements to an array
a.reverse();               // Another method: reverse the order of elements

// We can define our own methods, too. The "this" keyword refers to the object
// on which the method is defined: in this case, the points array from earlier.
points.dist = function() { // Define a method to compute distance between points
    let p1 = this[0];      // First element of array we're invoked on
    let p2 = this[1];      // Second element of the "this" object
    let a = p2.x-p1.x;     // Difference in x coordinates
    let b = p2.y-p1.y;     // Difference in y coordinates
    return Math.sqrt(a*a + // The Pythagorean theorem
                     b*b); // Math.sqrt() computes the square root
};
points.dist()              // => Math.sqrt(2): distance between our 2 points

Ahora, como prometí, he aquí algunas funciones cuyos cuerpos demuestran declaraciones comunes de la estructura de control de JavaScript:

// JavaScript statements include conditionals and loops using the syntax
// of C, C++, Java, and other languages.
function abs(x) {          // A function to compute the absolute value.
    if (x >= 0) {          // The if statement...
        return x;          // executes this code if the comparison is true.
    }                      // This is the end of the if clause.
    else {                 // The optional else clause executes its code if
        return -x;         // the comparison is false.
    }                      // Curly braces optional when 1 statement per clause.
}                          // Note return statements nested inside if/else.
abs(-10) === abs(10)       // => true

function sum(array) {      // Compute the sum of the elements of an array
    let sum = 0;           // Start with an initial sum of 0.
    for(let x of array) {  // Loop over array, assigning each element to x.
        sum += x;          // Add the element value to the sum.
    }                      // This is the end of the loop.
    return sum;            // Return the sum.
}
sum(primes)                // => 28: sum of the first 5 primes 2+3+5+7+11

function factorial(n) {    // A function to compute factorials
    let product = 1;       // Start with a product of 1
    while(n > 1) {         // Repeat statements in {} while expr in () is true
        product *= n;      // Shortcut for product = product * n;
        n--;               // Shortcut for n = n - 1
    }                      // End of loop
    return product;        // Return the product
}
factorial(4)               // => 24: 1*4*3*2

function factorial2(n) {   // Another version using a different loop
    let i, product = 1;    // Start with 1
    for(i=2; i <= n; i++)  // Automatically increment i from 2 up to n
        product *= i;      // Do this each time. {} not needed for 1-line loops
    return product;        // Return the factorial
}
factorial2(5)              // => 120: 1*2*3*4*5

JavaScript admite un estilo de programación orientado a objetos, pero es significativamente diferente de los lenguajes de programación orientados a objetos "clásicos". El capítulo 9 trata en detalle la programación orientada a objetos en JavaScript, con muchos ejemplos. Aquí hay un ejemplo muy sencillo que demuestra cómo definir una clase JavaScript para representar puntos geométricos 2D. Los objetos que son instancias de esta clase tienen un único método, llamado distance(), que calcula la distancia del punto al origen:

class Point {              // By convention, class names are capitalized.
    constructor(x, y) {    // Constructor function to initialize new instances.
        this.x = x;        // This keyword is the new object being initialized.
        this.y = y;        // Store function arguments as object properties.
    }                      // No return is necessary in constructor functions.

    distance() {           // Method to compute distance from origin to point.
        return Math.sqrt(  // Return the square root of x² + y².
            this.x * this.x +  // this refers to the Point object on which
            this.y * this.y    // the distance method is invoked.
        );
    }
}

// Use the Point() constructor function with "new" to create Point objects
let p = new Point(1, 1);   // The geometric point (1,1).

// Now use a method of the Point object p
p.distance()               // => Math.SQRT2

Este recorrido introductorio de por la sintaxis y las capacidades fundamentales de JavaScript termina aquí, pero el libro continúa con capítulos independientes que cubren características adicionales del lenguaje:

Capítulo 10, Módulos

Muestra cómo el código JavaScript de un archivo o script puede utilizar funciones y clases JavaScript definidas en otros archivos o scripts.

Capítulo 11, La biblioteca estándar de JavaScript

Cubre las funciones y clases incorporadas que están disponibles para todos los programas JavaScript. Esto incluye importantes estructuras de datos como mapas y conjuntos, una clase de expresión regular para la concordancia de patrones textuales, funciones para serializar estructuras de datos de JavaScript y mucho más.

Capítulo 12, Iteradores y generadores

Explica cómo funciona el bucle for/of y cómo puedes hacer iterables tus propias clases con for/of. También cubre las funciones generadoras y la sentencia yield.

Capítulo 13, JavaScript asíncrono

Este capítulo es una exploración en profundidad de la programación asíncrona en JavaScript, que abarca las devoluciones de llamada y los eventos, las API basadas en Promesas y las palabras clave async y await. Aunque el núcleo del lenguaje JavaScript no es asíncrono, las API asíncronas son las predeterminadas tanto en los navegadores web como en Node, y este capítulo explica las técnicas para trabajar con esas API.

Capítulo 14, Metaprogramación

Introduce una serie de características avanzadas de JavaScript que pueden ser de interés para los programadores que escriben bibliotecas de código para que las utilicen otros programadores de JavaScript.

Capítulo 15, JavaScript en los navegadores web

Introduce el entorno anfitrión del navegador web, explica cómo ejecutan código JavaScript los navegadores web y cubre las más importantes de las muchas API definidas por los navegadores web. Éste es, con diferencia, el capítulo más largo del libro.

Capítulo 16, JavaScript del lado del servidor con Node

Introduce el entorno anfitrión Node, cubriendo el modelo de programación fundamental y las estructuras de datos y API que es más importante comprender.

Capítulo 17, Herramientas y extensiones de JavaScript

Cubre herramientas y extensiones del lenguaje que merece la pena conocer porque se utilizan mucho y pueden hacer que seas un programador más productivo.

1.4 Ejemplo: Histogramas de frecuencia de caracteres

Este capítulo de concluye con un programa JavaScript breve pero no trivial. El Ejemplo 1-1 es un programa Node que lee texto de la entrada estándar, calcula un histograma de frecuencia de caracteres a partir de ese texto y luego imprime el histograma. Podrías invocar el programa así para analizar la frecuencia de caracteres de su propio código fuente:

$ node charfreq.js < charfreq.js
T: ########### 11.22%
E: ########## 10.15%
R: ####### 6.68%
S: ###### 6.44%
A: ###### 6.16%
N: ###### 5.81%
O: ##### 5.45%
I: ##### 4.54%
H: #### 4.07%
C: ### 3.36%
L: ### 3.20%
U: ### 3.08%
/: ### 2.88%

Este ejemplo utiliza una serie de funciones avanzadas de JavaScript y pretende demostrar cómo pueden ser los programas JavaScript del mundo real. No debes esperar entender todo el código todavía, pero ten por seguro que todo ello se explicará en los capítulos siguientes.

Ejemplo 1-1. Cálculo de histogramas de frecuencia de caracteres con JavaScript
/**
 * This Node program reads text from standard input, computes the frequency
 * of each letter in that text, and displays a histogram of the most
 * frequently used characters. It requires Node 12 or higher to run.
 *
 * In a Unix-type environment you can invoke the program like this:
 *    node charfreq.js < corpus.txt
 */

// This class extends Map so that the get() method returns the specified
// value instead of null when the key is not in the map
class DefaultMap extends Map {
    constructor(defaultValue) {
        super();                          // Invoke superclass constructor
        this.defaultValue = defaultValue; // Remember the default value
    }

    get(key) {
        if (this.has(key)) {              // If the key is already in the map
            return super.get(key);        // return its value from superclass.
        }
        else {
            return this.defaultValue;     // Otherwise return the default value
        }
    }
}

// This class computes and displays letter frequency histograms
class Histogram {
    constructor() {
        this.letterCounts = new DefaultMap(0);  // Map from letters to counts
        this.totalLetters = 0;                  // How many letters in all
    }

    // This function updates the histogram with the letters of text.
    add(text) {
        // Remove whitespace from the text, and convert to upper case
        text = text.replace(/\s/g, "").toUpperCase();

        // Now loop through the characters of the text
        for(let character of text) {
            let count = this.letterCounts.get(character); // Get old count
            this.letterCounts.set(character, count+1);    // Increment it
            this.totalLetters++;
        }
    }

    // Convert the histogram to a string that displays an ASCII graphic
    toString() {
        // Convert the Map to an array of [key,value] arrays
        let entries = [...this.letterCounts];

        // Sort the array by count, then alphabetically
        entries.sort((a,b) => {              // A function to define sort order.
            if (a[1] === b[1]) {             // If the counts are the same
                return a[0] < b[0] ? -1 : 1; // sort alphabetically.
            } else {                         // If the counts differ
                return b[1] - a[1];          // sort by largest count.
            }
        });

        // Convert the counts to percentages
        for(let entry of entries) {
            entry[1] = entry[1] / this.totalLetters*100;
        }

        // Drop any entries less than 1%
        entries = entries.filter(entry => entry[1] >= 1);

        // Now convert each entry to a line of text
        let lines = entries.map(
            ([l,n]) => `${l}: ${"#".repeat(Math.round(n))} ${n.toFixed(2)}%`
        );

        // And return the concatenated lines, separated by newline characters.
        return lines.join("\n");
    }
}

// This async (Promise-returning) function creates a Histogram object,
// asynchronously reads chunks of text from standard input, and adds those chunks to
// the histogram. When it reaches the end of the stream, it returns this histogram
async function histogramFromStdin() {
    process.stdin.setEncoding("utf-8"); // Read Unicode strings, not bytes
    let histogram = new Histogram();
    for await (let chunk of process.stdin) {
        histogram.add(chunk);
    }
    return histogram;
}

// This one final line of code is the main body of the program.
// It makes a Histogram object from standard input, then prints the histogram.
histogramFromStdin().then(histogram => { console.log(histogram.toString()); });

1.5 Resumen

Este libro de explica JavaScript de abajo arriba. Esto significa que empezamos con detalles de bajo nivel, como comentarios, identificadores, variables y tipos; luego pasamos a expresiones, sentencias, objetos y funciones; y finalmente cubrimos las abstracciones de alto nivel del lenguaje, como clases y módulos. Me tomo muy en serio la palabra "definitivo " del título de este libro, y los próximos capítulos explican el lenguaje con un nivel de detalle que puede resultar desconcertante al principio. Sin embargo, el verdadero dominio de JavaScript requiere comprender los detalles, y espero que dediques tiempo a leer este libro de principio a fin. Pero, por favor, no te sientas obligado a hacerlo en tu primera lectura. Si te sientes atascado en una sección, simplemente pasa a la siguiente. Podrás volver y dominar los detalles una vez que tengas un conocimiento práctico de la lengua en su conjunto.

Get JavaScript: La Guía Definitiva, 7ª Edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.