Articulo de referencia

Sintaxis de JavaScript

Un fragmento de código JavaScript con palabras clave resaltadas en diferentes colores. La sintaxis de JavaScript es el conjunto de reglas que definen un programa JavaScript corr...

Un fragmento de código JavaScript con palabras clave resaltadas en diferentes colores.

La sintaxis de JavaScript es el conjunto de reglas que definen un programa JavaScript correctamente estructurado.

Los ejemplos que se muestran a continuación utilizan la console.log()función presente en la mayoría de los navegadores para la salida de texto estándar .

La biblioteca estándar de JavaScript carece de una función oficial de salida de texto estándar (con la excepción de document.write). Dado que JavaScript se utiliza principalmente para la programación del lado del cliente dentro de los navegadores web modernos , y que casi todos los navegadores web proporcionan la función alert, alerttambién se puede utilizar, pero no es de uso común.

TypeScript , que extiende JavaScript con anotaciones de tipo y características adicionales, tiene la misma sintaxis, así como sus propias características adicionales.

Orígenes

Código JavaScript que muestra los días de la semana en un navegador.

Brendan Eich resumió la ascendencia de la sintaxis en el primer párrafo de la especificación JavaScript 1.1 [ 1 ] [ 2 ] de la siguiente manera:

JavaScript toma prestada la mayor parte de su sintaxis de Java , pero también hereda de Awk y Perl , con cierta influencia indirecta de Self en su sistema de prototipos de objetos.

La sintaxis de JavaScript se deriva principalmente de la sintaxis de Java , que a su vez se deriva de la sintaxis de C y de la sintaxis de C++ .

Lo esencial

Palabras clave

Palabras clave reservadas

Las siguientes palabras son palabras clave y no pueden utilizarse como identificadores bajo ninguna circunstancia.

  • async
  • break
  • case
  • catch
  • class
  • const
  • continue
  • debugger
  • default
  • delete
  • do
  • else
  • enum
  • eval
  • export
  • extends
  • finally
  • for
  • function
  • if
  • implements
  • import
  • in
  • instanceof
  • interface
  • let
  • new
  • package
  • private
  • protected
  • public
  • return
  • static
  • super
  • switch
  • this
  • throw
  • try
  • typeof
  • using
  • var
  • void
  • while
  • with
  • yield

Palabras reservadas para valores literales

Las siguientes palabras se refieren a valores literales utilizados por el idioma.

  • true
  • false
  • null

JavaScript también define las siguientes constantes globales, que no son palabras clave.

  • NaN
  • Infinity
  • undefined
  • globalThis

Palabras clave eliminadas

Las siguientes palabras, asociadas principalmente con Java, fueron eliminadas del estándar ECMAScript 5/6:

  • abstract
  • boolean
  • byte
  • char
  • double
  • final
  • float
  • goto
  • int
  • long
  • native
  • short
  • synchronized
  • throws
  • transient
  • volatile

Palabras clave de TypeScript

Las siguientes palabras adicionales son palabras clave en TypeScript.

  • abstract
  • any
  • as
  • declare
  • infer
  • keyof
  • module
  • namespace
  • never
  • readonly
  • type
  • unknown

Sensibilidad a mayúsculas y minúsculas

JavaScript distingue entre mayúsculas y minúsculas . Es común que el nombre de un constructor comience con una letra mayúscula y el de una función o variable con una letra minúscula.

Ejemplo:

var a = 5 ; console.log ( a ) ; // 5 console.log ( A ) ; // lanza un ReferenceError : A no está definido

Espacios en blanco y punto y coma

A diferencia de C , los espacios en blanco en el código fuente de JavaScript pueden afectar directamente la semántica . Los puntos y coma finalizan las sentencias en JavaScript. Debido a la inserción automática de punto y coma (ASI), algunas sentencias que están bien formadas cuando se analiza un salto de línea se considerarán completas, como si se hubiera insertado un punto y coma justo antes del salto de línea. Algunos expertos recomiendan proporcionar explícitamente los puntos y coma que finalizan las sentencias, ya que esto puede reducir los efectos no deseados de la inserción automática de punto y coma. [ 3 ]

Hay dos problemas: cinco tokens pueden iniciar una declaración o ser la extensión de una declaración completa; y cinco producciones restringidas, donde no se permiten saltos de línea en ciertas posiciones, lo que podría generar un análisis sintáctico incorrecto.

Los cinco tokens problemáticos son el paréntesis de apertura " (", el corchete de apertura " [", la barra inclinada " /", el signo más " +" y el signo menos " -". De estos, el paréntesis de apertura es común en el patrón de expresión de función invocada inmediatamente , el corchete de apertura aparece a veces, mientras que los demás son bastante raros. Un ejemplo:

a = b + c ( d + e ). foo ()// Se trata como: // a = b + c(d + e).foo();

con la sugerencia de que la declaración anterior termine con un punto y coma.

Algunos sugieren, en cambio, el uso de punto y coma al principio de las líneas que comienzan con ' (' o ' [', para evitar que la línea se una accidentalmente con la anterior. Esto se conoce como punto y coma defensivo y se emplea porque, de lo contrario, el código podría volverse ambiguo al reorganizarse. Por ejemplo:

a = b + c ( d + e ). foo ()// Se trata como: // a = b + c; // (d + e).foo();

En ocasiones, también se utilizan puntos y comas al inicio de las bibliotecas de JavaScript, por si se añaden a otra biblioteca que omita el punto y coma final, ya que esto puede generar ambigüedad en la instrucción inicial. En estos casos, donde la colocación del punto y coma puede ser inusual, quizás sea mejor colocarlo manualmente al final de las instrucciones.

Las cinco producciones restringidas son return, throw, break, continue, y post-incremento/decremento. En todos los casos, insertar puntos y comas no soluciona el problema, pero aclara la sintaxis analizada, facilitando la detección del error. returny throwtoman un valor opcional, mientras que breaky continuetoman una etiqueta opcional. En todos los casos, se recomienda mantener el valor o la etiqueta en la misma línea que la instrucción. Esto suele aparecer en la instrucción return, donde se podría devolver un literal de objeto grande, que podría colocarse accidentalmente comenzando en una nueva línea. Para post-incremento/decremento, existe una posible ambigüedad con pre-incremento/decremento, y nuevamente se recomienda simplemente mantenerlos en la misma línea.

devolver a + b ;// Devuelve indefinido. Se trata como: // return; // a + b; // Debería escribirse como: // return a + b;

Comentarios

La sintaxis de los comentarios es la misma que en C++ , Swift y otros lenguajes de programación.

Los comentarios de una sola línea comienzan con //y continúan hasta el final de la línea. También se puede hacer un segundo tipo de comentarios; estos comienzan con /*y terminan con */y se pueden usar para comentarios de varias líneas.

Un tercer tipo de comentario, el comentario hashbang, comienza con #!y continúa hasta el final de la línea. Solo son válidos al inicio de los archivos y están pensados ​​para su uso en entornos CLI . [ 4 ]

# ! Comentario de Hashbang// Comentario de una sola línea/* Comentario de varias líneas  */

Variables

Las variables en JavaScript estándar no tienen un tipo asociado, por lo que cualquier valor (cada valor tiene un tipo) puede almacenarse en cualquier variable. A partir de ES6 , la sexta versión del lenguaje, las variables podían declararse con varpara variables de ámbito de función, y leto constque son para variables de nivel de bloque . Antes de ES6, las variables solo podían declararse con una varinstrucción. Los valores asignados a variables declaradas con constno se pueden cambiar, pero sus propiedades sí. varya no debería usarse ya que lety constson compatibles con los navegadores modernos. [ 5 ] El identificador de una variable debe comenzar con una letra, un guion bajo ( _), o un signo de dólar ( $), mientras que los caracteres subsiguientes también pueden ser dígitos ( 0-9). JavaScript distingue entre mayúsculas y minúsculas, por lo que los caracteres en mayúscula " A " a " Z " son diferentes de los caracteres en minúscula " a " a " z ".

A partir de JavaScript 1.5, se pueden usar caracteres ISO 8859-1 o Unicode (o secuencias de escape Unicode) en los identificadores. [ 6 ] En ciertas implementaciones de JavaScript, se puede usar el signo arroba ( @ ) en un identificador, pero esto es contrario a las especificaciones y no es compatible con las implementaciones más recientes.\uXXXX

Alcance y elevación

Las variables declaradas con vartienen un alcance léxico a nivel de función , mientras que las que tienen leto consttienen un alcance a nivel de bloque . Dado que las declaraciones se procesan antes de que se ejecute cualquier código, una variable puede asignarse a y usarse antes de ser declarada en el código. [ 7 ] Esto se conoce comoel hoisting , y es equivalente a que las variables sedeclaren anticipadamenteen la parte superior de la función o bloque. [ 8 ]

Con las declaraciones var, let, y const, solo se eleva la declaración; las asignaciones no se elevan. Por lo tanto, una declaración en medio de la función es equivalente a una declaración al principio de la función y una asignación en ese punto en medio de la función. Esto significa que no se puede acceder a los valores antes de que se declaren; no es posible la referencia anticipada . Con , el valor de una variable es hasta que se inicializa. Las variables declaradas con o no se pueden acceder hasta que se hayan inicializado, por lo que hacer referencia a dichas variables antes provocará un error.varx=1varxx=1varundefinedletconst

Las declaraciones de funciones, que declaran una variable y le asignan una función , son similares a las sentencias de variables, pero además de elevar la declaración, también elevan la asignación (como si toda la sentencia apareciera al principio de la función contenedora), y por lo tanto, también es posible la referencia hacia adelante: la ubicación de una sentencia de función dentro de una función contenedora es irrelevante. Esto es diferente de la asignación de una expresión de función a una variable en una sentencia var, let, o .const

Entonces, por ejemplo,

var func = function () { .. } // solo se eleva la declaración function func () { .. } // se elevan tanto la declaración como la asignación

El ámbito de bloque se puede producir envolviendo todo el bloque en una función y luego ejecutándola (esto se conoce como el patrón de expresión de función invocada inmediatamente ) o declarando la variable usando la letpalabra clave.

Declaración y asignación

Las variables declaradas fuera de un ámbito son globales . Si una variable se declara en un ámbito superior, los ámbitos secundarios pueden acceder a ella.

Cuando JavaScript intenta resolver un identificador, lo busca en el ámbito local. Si no lo encuentra, lo busca en el siguiente ámbito externo, y así sucesivamente a lo largo de la cadena de ámbitos hasta llegar al ámbito global , donde residen las variables globales. Si aún no lo encuentra, JavaScript generará una ReferenceErrorexcepción.

Al asignar un identificador, JavaScript sigue exactamente el mismo proceso para recuperarlo, excepto que si no se encuentra en el ámbito global , creará la "variable" en el ámbito donde se creó. [ 9 ] Como consecuencia, una variable nunca declarada será global si se le asigna. Declarar una variable (con la palabra clave var) en el ámbito global (es decir, fuera de cualquier cuerpo de función (o bloque en el caso de let/const)), asignar un identificador nunca declarado o agregar una propiedad al objeto global (normalmente window ) también creará una nueva variable global.

Cabe destacar que el modo estricto de JavaScript prohíbe la asignación de una variable no declarada, lo que evita la contaminación del espacio de nombres global.

Ejemplos

Aquí hay algunos ejemplos de declaraciones de variables y ámbito:

var x1 = 0 ; // Una variable global, porque no está en ninguna función let x2 = 0 ; // También global, esta vez porque no está en ningún bloquefunción f () { var z = 'zorros' , r = 'pájaros' ; // 2 variables locales m = 'pez' ; // global, porque no se declaró en ningún lugar antesfunction child () { var r = 'monos' ; // Esta variable es local y no afecta a la variable "pájaros" r de la función padre. z = 'pingüinos' ; // Cierre: La función hija puede acceder a las variables de la función padre. }veinte = 20 ; // Esta variable se declara en la siguiente línea, pero se puede usar en cualquier parte de la función, incluso antes, como aquí var veinte ;hijo (); return x1 + x2 ; // Podemos usar x1 y x2 aquí, porque son globales }f ();console.log ( z ) ; // Esta línea generará una excepción ReferenceError, porque el valor de z ya no está disponible .
for ( let i = 0 ; i < 10 ; i ++ ) console . log ( i ); console . log ( i ); // lanza un ReferenceError: i no está definido
for ( const i = 0 ; i < 10 ; i ++ ) console . log ( i ); // lanza un TypeError: Assignment to constant variablefor ( const i of [ 1 , 2 , 3 ]) console . log ( i ); //no generará una excepción. i no se reasigna sino que se recrea en cada iteración.const pi ; // genera un SyntaxError: Falta el inicializador en la declaración const

Tipos de datos primitivos

El lenguaje JavaScript proporciona seis tipos de datos primitivos :

  • Undefined
  • Number
  • BigInt
  • String
  • Boolean
  • Symbol

Algunos tipos de datos primitivos también proporcionan un conjunto de valores con nombre que representan los límites de dichos tipos. Estos valores con nombre se describen en las secciones correspondientes a continuación.

Indefinido

El valor "undefined" se asigna a todas las variables no inicializadas y también se devuelve al comprobar propiedades de objetos que no existen. En un contexto booleano, el valor "undefined" se considera falso.

Nota: `undefined` se considera un tipo primitivo genuino. A menos que se convierta explícitamente, el valor `undefined` puede comportarse de forma inesperada en comparación con otros tipos que se evalúan como falsos en un contexto lógico.

let test ; // variable declarada, pero no definida, ... // ... se establece al valor de undefined const testObj = {}; console.log ( test ); // la variable test existe, pero el valor no ... // ... está definido, muestra undefined console.log ( testObj.myProp ); // testObj existe, la propiedad no, ... // ... muestra undefined console.log ( undefined == null ); // tipo no aplicado durante la comprobación, muestra true console.log ( undefined === null ); // tipo aplicado durante la comprobación, muestra false

Nota: No existe un literal de lenguaje incorporado para `undefined`. Por lo tanto, no es una forma infalible de comprobar si una variable es `undefined`, porque en versiones anteriores a ECMAScript 5, es válido que alguien escriba ` . Un enfoque más robusto es comparar usando `.(x===undefined)varundefined="I'm defined now";(typeofx==='undefined')

Funciones como esta no funcionarán como se espera:

función isUndefined ( x ) { let u ; return x === u ; } // así... función isUndefined ( x ) { return x === void 0 ; } // ... o esa segunda función isUndefined ( x ) { return ( typeof x ) === "undefined" ; } // ... o esa tercera

Aquí, llamar isUndefined(my_var)genera un ReferenceError si my_var es un identificador desconocido, mientras que no.typeofmy_var==='undefined'

Número

Los números se representan en binario como números de coma flotante de doble precisión IEEE 754. Si bien este formato ofrece una precisión de casi 16 dígitos significativos , no siempre puede representar con exactitud los números reales, incluidas las fracciones.

Esto se convierte en un problema al comparar o formatear números. Por ejemplo:

console.log ( 0.2 + 0.1 === 0.3 ); // muestra false console.log ( 0.94 - 0.01 ) ; // muestra 0.9299999999999999

Como resultado, se debe utilizar una rutina como el método toFixed() para redondear los números siempre que se formateen para su salida .

Los números pueden especificarse en cualquiera de estas notaciones:

345 ; // un "entero", aunque solo hay un tipo numérico en JavaScript 34.5 ; // un número de punto flotante 3.45e2 ; // otro número de punto flotante, equivalente a 345 0b1011 ; // un entero binario igual a 11 0o377 ; // un entero octal igual a 255 0xFF ; // un entero hexadecimal igual a 255, cuyos dígitos están representados por las ... // ... letras AF pueden ser mayúsculas o minúsculas

También existe un separador numérico, _ (el guion bajo), introducido en ES2021:

// Nota: La sintaxis de Wikipedia aún no admite separadores numéricos 1 _000_000_000 ; // Se usa con números grandes 1 _000_000 .5 ; // Admite decimales 1 _000e1_000 ; // Admite exponentes// Soporte con binario, octal y hexadecimal 0b0000 _0000_0101_1011 ; 0o0001 _3520_0237_1327 ; 0xFFFF _FFFF_FFFF_FFFE ;// Pero los usuarios no pueden usarlos junto a una parte numérica que no sea un dígito, ni al principio ni al final _12 ; // La variable no está definida (el guion bajo la convierte en un identificador de variable) 12 _ ; // Error de sintaxis (no puede estar al final de los números) 12 _ .0 ; // Error de sintaxis (no tiene sentido poner un separador junto al punto decimal) 12. _0 ; // Error de sintaxis 12 e_6 ; // Error de sintaxis (junto a "e", un no dígito. No tiene sentido poner un separador al principio) 1000 ____0000 ; // Error de sintaxis (junto a "_", un no dígito. Solo se permite 1 separador a la vez)

Los rangos +∞ , −∞ y NaN (Not a Number) del tipo numérico se pueden obtener mediante dos expresiones de programa :

Infinito ; // infinito positivo (negativo se obtiene con -Infinito, por ejemplo) NaN ; // El valor Not-A-Number, también devuelto como un error en ... // ... conversiones de cadena a número

Infinito y NaN son números:

typeof Infinity ; // devuelve "número" typeof NaN ; // devuelve "número"

Estos tres valores especiales se corresponden y se comportan como los describe la norma IEEE-754 .

El constructor Number (utilizado como función), o un operador unario + o -, pueden utilizarse para realizar conversiones numéricas explícitas:

const myString = "123.456" ; const myNumber1 = Number ( myString ); const myNumber2 = + myString ;

Cuando se utiliza como constructor, se crea un objeto contenedor numérico (aunque es de poca utilidad):

const myNumericWrapper = new Number ( 123.456 );

Sin embargo, NaN no es igual a sí mismo:

constante nan = NaN ; consola . iniciar sesión ( NaN == NaN ); // consola falsa . iniciar sesión ( NaN === NaN ); // consola falsa . iniciar sesión ( NaN ! == NaN ); // verdadera consola . iniciar sesión ( nan !== nan ); // verdadero// Los usuarios pueden usar los métodos isNaN para comprobar si hay NaN console.log ( isNaN ( " convertido a NaN" ) ); // verdadero console.log ( isNaN ( NaN ) ); // verdadero console.log ( Number.isNaN ( " no convertido" ) ); // falso console.log ( Number.isNaN ( NaN ) ) ; // verdadero

BigInt

En JavaScript, los números regulares se representan con el tipo de punto flotante IEEE 754, lo que significa que los enteros solo se pueden almacenar de forma segura si el valor se encuentra entre Number.MIN_SAFE_INTEGERy Number.MAX_SAFE_INTEGER. [ 10 ] En cambio, BigInts representa enteros de cualquier tamaño, lo que permite a los programadores almacenar enteros demasiado grandes o pequeños para ser representados con el formato IEEE 754. [ 11 ]

Hay dos maneras de declarar un valor BigInt. Se npuede agregar un entero o BigIntse puede usar la función: [ 11 ]

const a = 12345n ; // Crea una variable y almacena un valor BigInt de 12345 const b = BigInt ( 12345 );

Cadena

En JavaScript, una cadena" es una secuencia de caracteres. Las cadenas se pueden crear directamente (como literales) colocando la serie de caracteres entre comillas dobles ( ) o simples ( '). Dichas cadenas deben escribirse en una sola línea, pero pueden incluir caracteres de salto de línea escapados (como \n). El estándar de JavaScript permite el carácter de comilla invertida` ( , también conocido como acento grave o acento grave) para entrecomillar cadenas literales multilínea, así como expresiones incrustadas que utilizan la sintaxis . [ 12 ]${expression}

const greeting = "¡Hola, mundo!" ; const anotherGreeting = 'Saludos, gente de la Tierra.' ; const aMultilineGreeting = `Saludos cordiales, John Doe.`// Los literales de plantilla convierten a tipo las expresiones evaluadas y las interpolan en la cadena. const templateLiteral = `Esto es lo que se almacena en anotherGreeting: ${ anotherGreeting } .` ; console . log ( templateLiteral ); // 'Esto es lo que se almacena en anotherGreeting: 'Saludos, gente de la Tierra.'' console . log ( `Tienes ${ Math . floor ( age )=> 18 ? "permitido" : "no permitido" } para ver esta página web` );

Se puede acceder a caracteres individuales dentro de una cadena utilizando el método charAt (proporcionado por String.prototype ). Esta es la forma preferida de acceder a caracteres individuales dentro de una cadena, ya que también funciona en navegadores antiguos:

const h = greeting.charAt ( 0 ) ;

En los navegadores modernos, se puede acceder a los caracteres individuales dentro de una cadena (como cadenas con un solo carácter) mediante la misma notación que se utiliza para las matrices:

const h = saludo [ 0 ];

Sin embargo, las cadenas de JavaScript son inmutables :

saludo [ 0 ] = "H" ; // Falla.

Al aplicar el operador de igualdad ("==") a dos cadenas, el resultado es verdadero si las cadenas tienen el mismo contenido, es decir: la misma longitud y la misma secuencia de caracteres (las mayúsculas y minúsculas son importantes para los alfabetos). Por lo tanto:

const x = "World" ; const compare1 = ( "Hello, " + x == "Hello, World" ); // Aquí compare1 contiene true. const compare2 = ( "Hello, " + x == "hello, World" ); // Aquí compare2 contiene ... // ... false ya que los ... // ... primeros caracteres ... // ... de ambos operandos ... // ... no son de la misma mayúscula/minúscula.

Las citas del mismo tipo no se pueden anidar a menos que se escapen .

let x = '"¡Hola, mundo!" dijo.' ; // Bien. x = "" ¡Hola , mundo ! " dijo." ; // No está bien. x = "\"¡Hola, mundo!\" dijo." ; // Funciona escapando " con \"

El constructor String crea un objeto string (un objeto que encapsula una cadena):

const greeting = new String ( "Hola, mundo!" );

Estos objetos tienen un método valueOf que devuelve la cadena primitiva encapsulada en ellos :

const s = new String ( "Hello !" ); typeof s ; // Es 'object'. typeof s . valueOf (); // Es 'string'.

La igualdad entre dos objetos String no se comporta como con los tipos de datos primitivos de cadena:

const s1 = new String ( "Hello !" ); const s2 = new String ( "Hello !" ); s1 == s2 ; // Es falso, porque son dos objetos distintos. s1 . valueOf () == s2 . valueOf (); // Es verdadero.

Booleano

JavaScript proporciona un tipo de dato booleano con literales verdadero y falso . El operador `typeof` devuelve la cadena "boolean" para estos tipos primitivos . Cuando se utiliza en un contexto lógico, 0 , -0 , null , NaN , undefined y la cadena vacía ( "" ) se evalúan como falsos debido a la conversión automática de tipos . Todos los demás valores (el complemento de la lista anterior) se evalúan como verdaderos , incluidas las cadenas "0" , "false" y cualquier objeto.

Conversión de tipo

La coerción automática de tipos por parte de los operadores de comparación de igualdad ( ==y !=) se puede evitar utilizando los operadores de comparación con comprobación de tipos ( ===y !==).

Cuando se requiere conversión de tipo, JavaScript convierte los operandos Boolean , Number , String u Object de la siguiente manera: [ 13 ]

Número y cadena
La cadena se convierte en un valor numérico. JavaScript intenta convertir el literal numérico de la cadena a un valor de tipo Número. Primero, se obtiene un valor matemático a partir del literal numérico de la cadena. Luego, este valor se redondea al número entero más cercano.
Booleano
Si uno de los operandos es un valor booleano, el operando booleano se convierte en 1 si es verdadero o en 0 si es falso .
Objeto
Si se compara un objeto con un número o una cadena, JavaScript intenta devolver el valor predeterminado del objeto. Para ello, el objeto se convierte a un valor primitivo de tipo cadena o número mediante los métodos ` .valueOf()` o `.toString()` . Si esto falla, se genera un error en tiempo de ejecución.

Conversión de tipo booleano

Douglas Crockford defiende los términos "verdadero" y "falso" para describir cómo se comportan los valores de varios tipos cuando se evalúan en un contexto lógico, especialmente en lo que respecta a los casos límite. [ 14 ] Los operadores lógicos binarios devolvían un valor booleano en las primeras versiones de JavaScript, pero ahora devuelven uno de los operandos en su lugar. Se devuelve el operando izquierdo, si se puede evaluar como  : falso , en el caso de la conjunción : ( ), o verdadero , en el caso de la disyunción : ( ); de lo contrario, se devuelve el operando derecho. La coerción automática de tipos por parte de los operadores de comparación puede diferir para los casos de operandos mixtos compatibles con booleanos y números (incluidas cadenas que se pueden evaluar como un número, u objetos que se pueden evaluar como una cadena), porque el operando booleano se comparará como un valor numérico. Esto puede ser inesperado. Una expresión se puede convertir explícitamente a una primitiva booleana duplicando el operador de negación lógica : ( !! ), usando la función Boolean() , o usando el operador condicional : ( ).a && ba || bc ? t : f

// Conversión automática de tipos console.log(true == 2); // false... true → 1 !== 2 ← 2 console.log(false == 2 ) ; // false ... false → 0 !== 2 ← 2 console.log(true == 1 ) ; // true .... true → 1 === 1 ← 1 console.log( false == 0 ) ; // true .... false 0 === 0 0 console.log ( true == " 2 " ) ; // false ... true → 1 !== 2 ← "2" console.log ( false == " 2" ); // false ... false → 0 !== 2 ← "2" console.log ( true == "1" ) ; // verdadero.... verdadero → 1 === 1 ← "1" consola . iniciar sesión ( falso == "0" ); // verdadero.... falso → 0 === 0 ← "0" consola . iniciar sesión ( falso == "" ); // verdadero.... falso → 0 === 0 ← "" consola . iniciar sesión ( falso == NaN ); // falso... falso → 0 !== NaNconsole.log ( NaN == NaN ); // falso...... NaN no es equivalente a nada, incluido NaN .// Comparación con comprobación de tipos (sin conversión de tipos y valores) console.log ( true === 1 ); // false ...... los tipos de datos no coinciden// Coerción de tipo explícita console.log ( true === !! 2 ); // verdadero... los tipos de datos y los valores coinciden console.log (true === !! 0); // falso... los tipos de datos coinciden, pero los valores difieren console.log( 1 ? verdadero : falso ) ; // verdadero... solo ±0 y NaN son números "falsos" console.log( " 0 " ? verdadero : falso ) ; // verdadero ... solo la cadena vacía es " falsa " console.log ( Booleano ( { })); // verdadero... todos los objetos son "verdaderos "

El nuevo operador permite crear un contenedor de objeto para un tipo primitivo booleano. Sin embargo, el operador `typeof` no devuelve un valor booleano para el contenedor, sino un objeto . Dado que todos los objetos se evalúan como verdaderos , se debe usar un método como `.valueOf() ` o `.toString() ` para recuperar el valor encapsulado. Para una conversión explícita al tipo booleano, Mozilla recomienda usar la función `Boolean()` (sin `new` ) en lugar del objeto `Boolean`.

const b = new Boolean ( false ); // Objeto false {} const t = Boolean ( b ); // Booleano true const f = Boolean ( b.valueOf ( )); // Booleano false let n = new Boolean ( b ); // No recomendado n = new Boolean ( b.valueOf ( ) ); // Preferidoif ( 0 || - 0 || "" || null || undefined || b . valueOf () || ! new Boolean () || ! t ) { console . log ( "Nunca esto" ); } else if ([] && {} && b && typeof b === "object" && b . toString () === "false" ) { console . log ( "Siempre esto" ); }

Símbolo

Los símbolos son una característica introducida en ES6 . Se garantiza que cada símbolo es un valor único y se pueden usar para la encapsulación . [ 15 ]

Ejemplo:

let x = Symbol ( 1 ); const y = Symbol ( 1 ); x === y ; // => falseconst symbolObject = {}; const normalObject = {};// dado que x e y son únicos, // pueden usarse como claves únicas en un objeto symbolObject [ x ] = 1 ; symbolObject [ y ] = 2 ;symbolObject [ x ]; // => 1 symbolObject [ y ]; // => 2// en comparación con las teclas numéricas normales normalObject [ 1 ] = 1 ; normalObject [ 1 ] = 2 ; // sobrescribe el valor de 1normalObject [ 1 ]; // => 2// cambiar el valor de x no cambia la clave almacenada en el objeto x = Symbol ( 3 ); symbolObject [ x ]; // => indefinido// Cambiar x de nuevo solo crea otro símbolo único x = Symbol ( 1 ); symbolObject [ x ]; // => indefinido

También existen símbolos muy conocidos .

Una de ellas es Symbol.iterator; si algo implementa Symbol.iterator, es iterable:

const x = [ 1 , 2 , 3 , 4 ]; // x es un Array x [ Symbol . iterator ] === Array . prototype [ Symbol . iterator ]; // y los Arrays son iterablesconst xIterator = x [ Symbol.iterator ](); // La función [ Symbol.iterator ] debe proporcionar un iterador para x xIterator.next ( ) ; // { value: 1, done: false } xIterator.next ( ) ; // { value: 2, done: false } xIterator.next ( ); // { value: 3, done: false } xIterator.next ( ) ; // { value : 4, done: false } xIterator.next ( ); // { value: undefined, done: true } xIterator.next (); // { value: undefined, done: true }// Los bucles for..of iteran automáticamente los valores for ( const value of x ) { console . log ( value ); // 1 2 3 4 }// Los conjuntos también son iterables: [ Symbol . iterator ] in Set . prototype ; // truefor ( const value of new Set ([ 'apple' , 'orange' ])) { console . log ( value ); // "apple" "orange" }

Objetos nativos

El lenguaje JavaScript proporciona un conjunto de objetos nativos . Estos objetos nativos se consideran parte de la especificación de JavaScript. Independientemente del entorno JavaScript, este conjunto de objetos siempre debería estar disponible.

Formación

Un Array es un objeto JavaScript prototipado desde el Arrayconstructor diseñado específicamente para almacenar valores de datos indexados por claves enteras. Los Arrays, a diferencia del tipo Object básico, se prototipan con métodos y propiedades para ayudar al programador en tareas rutinarias (por ejemplo, join, slice, y push).

Al igual que en la familia C , los arreglos utilizan un esquema de indexación basado en cero: un valor que se inserta en un arreglo vacío mediante el pushmétodo ocupa el índice 0 del arreglo.

const myArray = []; // Apunta la variable myArray a un Array vacío recién creado . myArray.push ( "hello World" ); // Rellena el siguiente índice vacío, en este caso 0. console.log(myArray [ 0 ] ) ; // Equivalente a console.log("hello World");

Los arreglos tienen una lengthpropiedad que siempre será mayor que el índice entero más grande utilizado en el arreglo. Esta propiedad se actualiza automáticamente si se crea una propiedad con un índice aún mayor. Al escribir un número menor en la lengthpropiedad, se eliminarán los índices mayores.

ArraySe puede acceder a los elementos de s utilizando la notación normal de acceso a las propiedades de los objetos:

myArray [ 1 ]; // el segundo elemento en myArray myArray [ "1" ];

Las dos opciones anteriores son equivalentes. No es posible utilizar la notación de "punto" ni cadenas con representaciones alternativas del número:

myArray .1 ; // error de sintaxis myArray [ "01" ]; // no es lo mismo que myArray[1]

La declaración de un array puede realizarse mediante un Arrayliteral o mediante el Arrayconstructor:

sea ​​miArray ;// Literales de matriz myArray = [ 1 , 2 ]; // longitud de 2 myArray = [ 1 , 2 ,]; // misma matriz - Los usuarios también pueden tener una coma adicional al final// También es posible no rellenar partes del array myArray = [ 0 , 1 , /* hueco */ , /* hueco */ , 4 , 5 ]; // longitud de 6 myArray = [ 0 , 1 , /* hueco */ , /* hueco */ , 4 , 5 ,]; // mismo array myArray = [ 0 , 1 , /* hueco */ , /* hueco */ , 4 , 5 , /* hueco */ ,]; // longitud de 7// Con el constructor myArray = new Array ( 0 , 1 , 2 , 3 , 4 , 5 ); // longitud de 6 myArray = new Array ( 365 ); // un array vacío con longitud 365

Los arreglos se implementan de manera que solo los elementos definidos usan memoria; son " arreglos dispersos ". Configurar y solo usa espacio para estos dos elementos, al igual que cualquier otro objeto. El del arreglo seguirá siendo reportado como 58. La longitud máxima de un arreglo es 4,294,967,295 que corresponde al número binario de 32 bits (11111111111111111111111111111111) 2 .myArray[10]='someThing'myArray[57]='somethingOther'length

Se puede utilizar la declaración literal de objeto para crear objetos que se comportan de forma muy similar a los arreglos asociativos en otros lenguajes:

const perro = { color : "marrón" , tamaño : "grande" }; perro [ "color" ]; // da como resultado "marrón" perro . color ; // también da como resultado "marrón"

Se pueden usar las declaraciones literales de objetos y matrices para crear rápidamente matrices asociativas, multidimensionales o ambas. (Técnicamente, JavaScript no admite matrices multidimensionales, pero se pueden simular con matrices de matrices).

const cats = [{ color : "brown" , size : "large" }, { color : "black" , size : "small" }]; cats [ 0 ][ "size" ]; // da como resultado "large"const dogs = { rover : { color : "brown" , size : "large" }, spot : { color : "black" , size : "small" }}; dogs [ "spot" ][ "size" ]; // da como resultado "small" dogs . rover . color ; // da como resultado "brown"

Fecha

Un Dateobjeto almacena un contador de milisegundos con signo, donde cero representa el 1 de enero de 1970 a las 00:00:00 UT y un rango de ±10⁸ días . Existen varias formas de proporcionar argumentos al Dateconstructor. Tenga en cuenta que los meses comienzan en cero.

new Date (); // crea una nueva instancia de Date que representa la hora/fecha actual. new Date ( 2010 , 2 , 1 ); // crea una nueva instancia de Date que representa 2010-Mar-01 00:00:00 new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // crea una nueva instancia de Date que representa 2010-Mar-01 14:25:30 new Date ( "2010-3-1 14:25:30" ); // crea una nueva instancia de Date a partir de una String.

Se proporcionan métodos para extraer campos, así como una herramienta útil toString:

const d = new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // 2010-Mar-01 14:25:30;// Muestra '2010-3-1 14:25:30': console . log ( d . getFullYear () + '-' + ( d . getMonth () + 1 ) + '-' + d . getDate () + ' ' + d . getHours () + ':' + d . getMinutes () + ':' + d . getSeconds ());// El método toString integrado devuelve algo como 'Mon 1 March, 2010 14:25:30 GMT-0500 (EST)': console . log ( d );

Error

Se pueden crear mensajes de error personalizados utilizando la Errorclase:

lanzar nuevo Error ( "Algo salió mal." );

Estas excepciones pueden ser capturadas por bloques try...catch...finally como se describe en la sección sobre manejo de excepciones .

Matemáticas

El objeto Math contiene varias constantes relacionadas con las matemáticas (por ejemplo, π ) y funciones (por ejemplo, coseno). (Tenga en cuenta que el objeto Math no tiene constructor, a diferencia de Array o Date . Todos sus métodos son "estáticos", es decir, métodos de "clase"). Todas las funciones trigonométricas utilizan ángulos expresados ​​en radianes , no en grados ni en grados centesimales .

Expresión regular

/expresión/ . prueba ( cadena ); // devuelve un valor booleano "cadena" . búsqueda ( /expresión/ ); // devuelve un número de posición "cadena" . reemplazo ( /expresión/ , reemplazo );// Aquí hay algunos ejemplos if ( /Tom/ . test ( "Mi nombre es Tom" )) console . log ( "Hola Tom!" ); console . log ( "Mi nombre es Tom" . search ( /Tom/ )); // == 11 (letras antes de Tom) console . log ( "Mi nombre es Tom" . replace ( /Tom/ , "John" )); // == "Mi nombre es John"

Clases de personajes

// \d - dígito // \D - no dígito // \s - espacio // \S - no espacio // \w - carácter de palabra // \W - no palabra // [ ] - uno de // [^] - uno que no es // - - rangoif ( /\d/ . test ( '0' )) console . log ( 'Dígito' ); if ( /[0-9]/ . test ( '6' )) console . log ( 'Dígito' ); if ( /[13579]/ . test ( '1' )) console . log ( 'Número impar' ); if ( /\S\S\s\S\S\S\S/ . test ( 'Mi nombre' )) console . log ( 'Formato correcto' ); if ( /\w\w\w/ . test ( 'Tom' )) console . log ( 'Hola Tom' ); if ( /[a-zA-Z]/ . test ( 'B' )) console . log ( 'Letra' );

Coincidencia de caracteres

// A...Z a...z 0...9 - alfanumérico // \u0000...\uFFFF - hexadecimal Unicode // \x00...\xFF - hexadecimal ASCII // \t - tabulación // \n - nueva línea // \r - retorno de carro // . - cualquier carácter // | - ORif ( /Tm/ . test ( 'Tom' )) console . log ( 'Hola Tom, Tam o Tim' ); if ( /A|B/ . test ( "A" )) console . log ( 'A o B' );

Repetidores

// ? - 0 o 1 coincidencia // * - 0 o más // + - 1 o más // {n} - exactamente n // {n,} - n o más // {0,n} - n o menos // {n,m} - rango de n a mif ( /ab?c/ . test ( "ac" )) console . log ( "OK" ); // coincidencia: "ac", "abc" if ( /ab*c/ . test ( "ac" )) console . log ( "OK" ); // coincidencia: "ac", "abc", "abbc", "abbbc" etc. if ( /ab+c/ . test ( "abc" )) console . log ( "OK" ); // coincidencia: "abc", "abbc", "abbbc" etc. if ( /ab{3}c/ . test ( "abbbc" )) console . log ( "OK" ); // coincidencia: "abbbc" if ( /ab{3,}c/ . test ( "abbbc" )) console . log ( "OK" ); // coincidencia: "abbbc", "abbbbc", "abbbbbc", etc. if ( /ab{1,3}c/ . test ( "abc" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "abc", "abbc", "abbbc"

Anclas

// ^ - la cadena comienza con // $ - la cadena termina conif ( /^My/ . test ( "My name is Tom" )) console . log ( "¡Hola!" ); if ( /Tom$/ . test ( "My name is Tom" )) console . log ( "¡Hola Tom!" );

Subexpresión

// ( ) - agrupa caracteresif ( /water(mark)?/ . test ( "watermark" )) console . log ( "¡Aquí hay agua!" ); // match: "water", "watermark", if ( /(Tom)|(John)/ . test ( "John" )) console . log ( "¡Hola Tom o John!" );

Banderas

// /g - global // /i - ignorar mayúsculas/minúsculas // /m - permitir coincidencias que abarquen varias líneasconsole.log ( "¡Hola Tom!".replace(/Tom/i, "John")); // == "¡Hola John!" console.log("ratatam".replace ( / ta / , " tu " ) ) ; // == " ratutam " console.log ( " ratatam " .replace ( / ta / g , " tu " ) ) ; // == "ratutum"

Métodos avanzados

mi_array = mi_cadena . split ( mi_delimitador ); // ejemplo mi_array = "perro,gato,vaca" . split ( "," ); // mi_array==["perro","gato","vaca"];my_array = my_string . match ( my_expression ); // ejemplo my_array = "Comenzamos a las 11:30, 12:15 y 16:45" . match ( /\d\d:\d\d/g ); // my_array==["11:30","12:15","16:45"];

Capturar grupos

const myRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/ ; const results = myRe . exec ( "La fecha y hora son 2009-09-08 09:37:08." ); if ( results ) { console . log ( "Coincidencia: " + results [ 0 ]); // Coincidencia completa const my_date = results [ 1 ]; // Primer grupo == "2009-09-08" const my_time = results [ 2 ]; // Segundo grupo == "09:37:08" console . log ( `Es ${ my_time } el ${ my_date } ` ); } else console . log ( "¡No se encontró una fecha válida!" );

Función

Cada función en JavaScript es una instancia del Functionconstructor :

// x, y es el argumento. 'return x + y' es el cuerpo de la función, que es el último en la lista de argumentos. const add = new Function ( 'x' , 'y' , 'return x + y' ); add ( 1 , 2 ); // => 3

La función de suma anterior también se puede definir mediante una expresión de función:

const add = function ( x , y ) { return x + y ; }; add ( 1 , 2 ); // => 3

En ES6, se agregó la sintaxis de función flecha, lo que permite que las funciones que devuelven un valor sean más concisas. También conservan el thisdel objeto global en lugar de heredarlo del lugar donde se llamó o sobre qué se llamó, a diferencia de la function() {}expresión.

const add = ( x , y ) => { return x + y ;}; // Los valores también se pueden devolver implícitamente (es decir, no se necesita una instrucción return) const addImplicit = ( x , y ) => x + y ;agregar ( 1 , 2 ); // => 3 agregarImplícito ( 1 , 2 ) // => 3

Para las funciones que necesitan ser elevadas, existe una expresión separada:

función agregar ( x , y ) { return x + y ; } agregar ( 1 , 2 ); // => 3

El sistema de elevación permite a los usuarios utilizar la función antes de que sea "declarada":

add ( 1 , 2 ); // => 3, no es una función ReferenceError add ( x , y ) { return x + y ; }

Una instancia de función tiene propiedades y métodos.

función restar ( x , y ) { return x - y ; }console.log ( subtract.length ); // = > 2 , aridad de la función (número de argumentos ) console.log ( subtract.toString ( ) ) ;/* "función restar(x, y) {  return x - y; }" */

Operadores

El operador '+' está sobrecargado : se utiliza para la concatenación de cadenas y la suma aritmética. Esto puede causar problemas al mezclar accidentalmente cadenas y números. Como operador unario, puede convertir una cadena numérica en un número.

// Concatenar 2 cadenas console.log ( ' He' + 'llo' ); // muestra Hello// Sumar dos números console.log ( 2 + 6 ); // muestra 8// Sumar un número y una cadena da como resultado una concatenación (de izquierda a derecha) console.log ( 2 + ' 2 ' ); // muestra 22 console.log ( '$' + 3 + 4 ); // muestra $34, pero se esperaba $7 console.log ( ' $' + ( 3 + 4 )); // muestra $7 console.log ( 3 + 4 + ' 7' ); // muestra 77, los números siguen siendo números hasta que se agrega una cadena// Convierte una cadena a un número usando el operador unario más console.log ( + ' 2 ' === 2 ); // muestra true console.log ( + ' Hola' ); // muestra NaN

De forma similar, el operador '*' está sobrecargado: puede convertir una cadena en un número.

console.log ( 2 + ' 6 ' * 1 ); // muestra 8 console.log ( 3 * ' 7' ); // 21 console.log ( ' 3' * '7' ); // 21 console.log ( ' hello ' * ' world' ) ; // muestra NaN

Aritmética

JavaScript admite los siguientes operadores aritméticos binarios :

JavaScript admite los siguientes operadores aritméticos unarios :

let x = 1 ; console.log ( ++ x ); // x se convierte en 2; muestra 2 console.log(x++); // muestra 2; x se convierte en 3 console.log( x ) ; // x es 3 ; muestra 3 console.log( x-- ) ; // muestra 3 ; x se convierte en 2 console.log ( x ) ; // muestra 2 ; x es 2 console.log ( -- x ) ; // x se convierte en 1; muestra 1

El operador módulo muestra el resto de la división por el módulo. Si intervienen números negativos, el valor devuelto depende del operando.

const x = 17 ; console.log ( x % 5 ) ; // muestra 2 console.log ( x % 6 ) ; // muestra 5 console.log ( -x % 5 ); // muestra -2 console.log ( -x % -5 ) ; // muestra -2 console.log ( x % -5 ) ; // muestra 2

Para que siempre se obtenga un número no negativo, los usuarios pueden volver a sumar el módulo y aplicar de nuevo el operador módulo:

const x = 17 ; console.log (( - x % 5 + 5 ) % 5 ); // muestra 3

Los usuarios también podrían hacer lo siguiente:

const x = 17 ; console.log ( Math.abs ( -x % 5 ) ) ; // también 3

Asignación

Asignación de tipos primitivos

let x = 9 ; x += 1 ; console.log ( x ); // muestra: 10 x *= 30 ; console.log ( x ); // muestra : 300 x /= 6 ; console.log ( x ); // muestra: 50 x - = 3 ; console.log ( x ) ; // muestra: 47 x % = 7 ; console.log ( x ) ; // muestra : 5

Asignación de tipos de objetos

/** * Para aprender sobre objetos JavaScript... */ const object_1 = { a : 1 }; // asigna la referencia del objeto recién creado a object_1 let object_2 = { a : 0 }; let object_3 = object_2 ; // object_3 hace referencia al mismo objeto que object_2 object_3 . a = 2 ; message (); // muestra 1 2 2 object_2 = object_1 ; // object_2 ahora hace referencia al mismo objeto que object_1 // object_3 todavía hace referencia a lo que object_2 hacía referencia antes message (); // muestra 1 1 2 object_2 . a = 7 ; // modifica object_1 message (); // muestra 7 7 2objeto_3.a = 5 ; // objeto_3 no cambia objeto_2 mensaje ( ); // muestra 7 7 5objeto_3 = objeto_2 ; objeto_3.a = 4 ; // objeto_3 cambia objeto_1 y objeto_2 mensaje ( ); // muestra 4 4 4/** * Imprime el mensaje en la consola */ function message () { console . log ( object_1 . a + " " + object_2 . a + " " + object_3 . a ); }

Tarea de desestructuración

En JavaScript de Mozilla, desde la versión 1.7, la asignación por desestructuración permite asignar partes de estructuras de datos a varias variables a la vez. El lado izquierdo de una asignación es un patrón que se asemeja a un literal de objeto/matriz anidado arbitrariamente que contiene l-lvalues ​​en sus hojas, los cuales recibirán las subestructuras del valor asignado.

let a , b , c , d , e ; [ a , b , c ] = [ 3 , 4 , 5 ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // muestra: 3,4,5 e = { foo : 5 , bar : 6 , baz : [ 'Baz' , 'Content' ]}; const arr = []; ({ baz : [ arr [ 0 ], arr [ 3 ]], foo : a , bar : b } = e ); console . log ( ` ${ a } , ${ b } , ${ arr } ` ); // muestra: 5,6,Baz,,,Content [ a , b ] = [ b , a ]; // intercambia el contenido de a y b console . log ( a + ',' + b ); // muestra: 6,5[ a , b , c ] = [ 3 , 4 , 5 ]; // permutaciones [ a , b , c ] = [ b , c , a ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // muestra: 4,5,3

Operador de extensión/descanso

El estándar ECMAScript 2015 introdujo el ...operador de matriz " ", para los conceptos relacionados de "sintaxis de propagación" [ 16 ] y "parámetros rest". [ 17 ] La propagación de objetos se agregó en ECMAScript 2018.

La sintaxis de propagación ofrece otra forma de desestructurar matrices y objetos. En el caso de las matrices, indica que los elementos deben usarse como parámetros en una llamada a función o como elementos de un literal de matriz. En el caso de los objetos, se puede usar para combinarlos o sobrescribir propiedades.

En otras palabras, " ..." transforma " [...foo]" en " [foo[0], foo[1], foo[2]]", y " this.bar(...foo);" en " this.bar(foo[0], foo[1], foo[2]);", y " { ...bar }" en { prop: bar.prop, prop2: bar.prop2 }.

const a = [ 1 , 2 , 3 , 4 ];// Se puede usar varias veces en la misma expresión.const b = [... a , ... a ]; // b = [1, 2, 3, 4, 1, 2, 3, 4];// Se puede combinar con artículos que no se extienden.const c = [ 5 , 6 , ... a , 7 , 9 ]; // c = [5, 6, 1, 2, 3, 4, 7, 9];// Para comparar, haciendo esto sin el operador de propagación// crea un array anidado.const d = [ a , a ]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]// Funciona igual con las llamadas a funcionesfunción foo ( arg1 , arg2 , arg3 ) {console.log ( ` ${ arg1 } : ${ arg2 } : $ { arg3 } ` ) ;}// Los usuarios pueden usarlo incluso si pasa más parámetros de los que la función utilizará.foo (... un ); // "1:2:3" → foo(a[0], a[1], a[2], a[3]);// Los usuarios pueden combinarlo con parámetros que no sean de propagación.foo ( 5 , ... a , 6 ); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);// Para comparar, haciendo esto sin el operador de propagación// Asigna el array a arg1 y nada a los demás parámetros.foo ( a ); // "1,2,3,4:undefined:undefined"const barra = { a : 1 , b : 2 , c : 3 };// Esto copiaría el objetoconst copy = { ... bar }; // copy = { a: 1, b: 2, c: 3 };// Aquí se sobrescribiría la "b".const override = { ... bar , b : 4 }; // override = { a: 1, c: 3, b: 4 }

Cuando ...se utiliza en la declaración de una función , indica un parámetro de resto . El parámetro de resto debe ser el último parámetro con nombre en la lista de parámetros de la función. Se le asignará un Arrayque contiene cualquier argumento pasado a la función que exceda los demás parámetros con nombre. En otras palabras, recibe "el resto" de los argumentos pasados ​​a la función (de ahí su nombre).

función foo ( a , b , ... c ) { console . log ( c . length ); }foo ( 1 , 2 , 3 , 4 , 5 ); // "3" → c = [3, 4, 5] foo ( 'a' , 'b' ); // "0" → c = []

Los parámetros REST son similares a los objetos de JavaScript arguments, que son objetos tipo array que contienen todos los parámetros (con nombre y sin nombre) de la llamada a la función actual. argumentsSin embargo, a diferencia de estos, los parámetros REST son objetos propiamente dichos , por lo que se pueden usar Arraymétodos como `request` .slice()y `request` directamente sobre ellos..sort()

Comparación

Las variables que hacen referencia a objetos son iguales o idénticas solo si hacen referencia al mismo objeto:

const obj1 = { a : 1 }; const obj2 = { a : 1 }; const obj3 = obj1 ; console . log ( obj1 == obj2 ); //false console . log ( obj3 == obj1 ); //true console . log ( obj3 === obj1 ); //true

Véase también Cadena .

Lógico

JavaScript proporciona cuatro operadores lógicos:

En el contexto de una operación lógica, cualquier expresión se evalúa como verdadera excepto la siguiente :

  • Cadenas: "", '',
  • Números: 0, -0, NaN,
  • Especial: null, undefined,
  • Booleano: false.

La función booleana se puede utilizar para convertir explícitamente a un tipo primitivo Boolean:

// Solo las cadenas vacías devuelven falso console.log ( Boolean ( " " ) === false ); console.log ( Boolean ( "false" ) === true ) ; console.log ( Boolean ( " 0" ) === true ) ;// Solo cero y NaN devuelven falso console.log ( Boolean ( NaN ) === false ); console.log ( Boolean ( 0 ) === false ) ; console.log ( Boolean ( -0 ) === false ); // equivalente a -1 * 0 console.log ( Boolean ( -2 ) === true ) ;// Todos los objetos devuelven true console.log ( Boolean ( this ) === true ); console.log ( Boolean ( {}) === true ); console.log ( Boolean ([ ] ) === true ) ;// Estos tipos devuelven false console.log ( Boolean ( null ) === false ); console.log ( Boolean ( undefined ) === false ); // equivalente a Boolean ( )

El operador NOT evalúa su operando como un booleano y devuelve la negación. Al usar el operador dos veces seguidas, como una doble negación , se convierte explícitamente una expresión en un tipo primitivo booleano:

console.log ( ! 0 === Booleano ( ! 0 ) ); console.log ( Booleano ( ! 0 ) === !! 1 ) ; console.log ( !! 1 === Booleano ( 1 ) ); console.log ( !! 0 === Booleano ( 0 ) ) ; console.log ( Booleano ( 0 ) === ! 1 ) ; console.log ( ! 1 === Booleano ( ! 1 )); console.log ( ! " " === Booleano ( ! " " ) ) ; console.log ( Booleano ( ! " " ) === !! " s" ); console.log ( !! "s" === Booleano ( " s " ) ) ; console.log ( !! " " === Booleano ( " " ) ) ; console . console.log ( Booleano ( "" ) === ! "s" ) ; console.log ( ! " s" === Booleano ( ! "s" ));

El operador ternario también se puede utilizar para la conversión explícita:

console.log ([] == false); console.log([] ? true : false); // “verdadero”, pero la comparación usa [].toString() console.log([0] == false); console.log ( [ 0 ] ? true : false ) ; // [ 0 ] .toString ( ) == " 0 " console.log ( " 0 " == false ) ; console.log ( " 0 " ? true : false ) ; // " 0 " 0 ... ( 0 == 0 ) ... 0 false console.log ([ 1 ] == true ) ; console.log ([ 1 ] ? true : false ) ; // [1].toString() == "1" console.log ( " 1" == true ); console.log ( " 1" ? true : false ); // "1" → 1 ... ( 1 == 1) ... 1 ← true console.log ([ 2 ] ! = true ) ; console.log([2] ? true : false); // [2].toString() == "2" console.log( " 2 " ! = true ) ; console.log ( " 2 " ? true : false ) ; // " 2 " 2 ... ( 2 != 1) ... 1 ← true

Las expresiones que utilizan características como el post-incremento ( i++) tienen un efecto secundario previsto . JavaScript proporciona evaluación de cortocircuito de expresiones; el operando derecho solo se ejecuta si el operando izquierdo no es suficiente para determinar el valor de la expresión.

console.log ( a || b ); // Cuando a es verdadero, no hay razón para evaluar b. console.log ( a && b ); // Cuando a es falso, no hay razón para evaluar b. console.log ( c ? t : f ) ; // Cuando c es verdadero , no hay razón para evaluar f .

En las primeras versiones de JavaScript y JScript , los operadores lógicos binarios devolvían un valor booleano (como la mayoría de los lenguajes de programación derivados de C). Sin embargo, todas las implementaciones contemporáneas devuelven uno de sus operandos:

console.log ( a || b ); // si a es verdadero , devuelve a, de lo contrario devuelve b console.log ( a && b ) ; // si a es falso, devuelve a, de lo contrario devuelve b

Los programadores más familiarizados con el comportamiento en C podrían encontrar esta característica sorprendente, pero permite una expresión más concisa de patrones como la fusión de nulos :

const s = t || "(default)" ; // asigna t, o el valor predeterminado, si t es nulo, vacío, etc.

Asignación lógica

Bitwise

JavaScript admite los siguientes operadores binarios bit a bit :

Ejemplos:

const x = 11 & 6 ; console.log ( x ) ; // 2

JavaScript admite el siguiente operador bit a bit unario :

Asignación bit a bit

JavaScript admite los siguientes operadores de asignación binaria:

Ejemplos:

let x = 7 ; console.log ( x ) ; // 7 x << = 3 ; console.log ( x ) ; // 7->14->28-> 56

Cadena

Ejemplos:

let cadena = "ab" + "cd" ; // cadena "abcd" += "e" ; // "abcd"const str2 = "2" + 2 ; // "22", no "4" ni 4.

???

El operador más cercano de JavaScript?? es , el "operador de coalescencia nula", que se agregó al estándar en la 11.ª edición de ECMAScript . [ 18 ] En versiones anteriores, se podía usar a través de un complemento de Babel y en TypeScript . Evalúa su operando izquierdo y, si el valor resultante no es "nulo" ( nullo undefined), toma ese valor como su resultado; de lo contrario, evalúa el operando derecho y toma el valor resultante como su resultado.

En el siguiente ejemplo, ase le asignará el valor de bsi el valor de bno es nullo undefined, de lo contrario se le asignará 3.

const a = b ?? 3 ;

Antes del operador de coalescencia nula, los programadores usaban el operador lógico OR ( ||). Pero mientras que ??busca específicamente nullo undefined, el ||operador busca cualquier valor falsonull : , undefined, "", 0, NaN, y por supuesto, false.

En el siguiente ejemplo, ase le asignará el valor de bsi el valor de bes verdadero , de lo contrario se le asignará 3.

const a = b || 3 ;

Estructuras de control

Declaraciones compuestas

Un par de llaves y una secuencia de instrucciones entre ellas constituyen una instrucción compuesta, que puede utilizarse en cualquier lugar donde se pueda utilizar una instrucción.{ }

Si... de lo contrario

if ( expr ) { //instrucciones; } else if ( expr2 ) { //instrucciones; } else { //instrucciones; }

Operador condicional (ternario)

El operador condicional crea una expresión que se evalúa como una de dos expresiones según una condición. Esto es similar a la instrucción `if` , que selecciona una de dos instrucciones para ejecutar según una condición. Es decir, el operador condicional es a las expresiones lo que ` if` es a las instrucciones.

const resultado = condición ? expresión : alternativa ;

es lo mismo que:

if ( condición ) { const resultado = expresión ; } else { const resultado = alternativa ; }

A diferencia de la instrucción if , el operador condicional no puede omitir su "rama else".

Sentencia switch

La sintaxis de la instrucción switch de JavaScript es la siguiente:

switch ( expr ) { case SOMEVALUE : // instrucciones; break ; case ANOTHERVALUE : // instrucciones para cuando ANOTHERVALUE || ORANOTHERONE // sin instrucción break, se pasa al siguiente caso case ORANOTHERONE : // instrucciones específicas para ORANOTHERONE (es decir, !ANOTHERVALUE && ORANOTHER); break ; // Aquí termina todo. case YETANOTHER : // instrucciones; break ; default : // instrucciones; break ; }
  • break;Es opcional; sin embargo, suele ser necesario, ya que de lo contrario la ejecución del código continuará en el cuerpo del siguiente bloque case. Este comportamiento de ejecución secuencial se puede utilizar cuando el mismo conjunto de instrucciones se aplica en varios casos, creando efectivamente una disyunción entre ellos.
  • Agregue una instrucción break al final del último caso como medida de precaución, en caso de que se agreguen casos adicionales posteriormente.
  • También se pueden utilizar valores literales de cadena para los valores de caso.
  • Se pueden utilizar expresiones en lugar de valores.
  • El caso predeterminado (opcional) se ejecuta cuando la expresión no coincide con ninguno de los otros casos especificados.
  • Se requieren aparatos de ortodoncia.

Bucle for

La sintaxis del bucle for de JavaScript es la siguiente:

for ( inicial ; condición ; instrucción del bucle ) { /*  Las instrucciones se ejecutarán cada vez  que el bucle for{} se repita, mientras  se cumpla la condición  */ }

o

para ( inicial ; condición ; instrucción de bucle ( iteración )) // una instrucción

Para ... en bucle

La sintaxis de JavaScript for ... in loopes la siguiente:

for ( var property_name in some_object ) { // instrucciones que utilizan some_object[property_name]; }
  • Itera a través de todas las propiedades enumerables de un objeto.
  • Recorre todos los índices utilizados del array, incluyendo todas las propiedades definidas por el usuario, si las hubiera. Por lo tanto, puede ser mejor usar un bucle for tradicional con un índice numérico al iterar sobre arrays.
  • Existen diferencias entre los distintos navegadores web con respecto a las propiedades que se reflejarán en la instrucción de bucle `for...in`. En teoría, esto se controla mediante una propiedad de estado interna definida por el estándar ECMAscript llamada "DontEnum", pero en la práctica, cada navegador devuelve un conjunto de propiedades ligeramente diferente durante la introspección. Es útil comprobar una propiedad determinada utilizando . Por lo tanto, añadir un método al prototipo de matriz con puede provocar que los bucles iteren sobre el nombre del método.if(some_object.hasOwnProperty(property_name)){...}Array.prototype.newMethod=function(){...}for ... in

Bucle while

La sintaxis del bucle while de JavaScript es la siguiente:

mientras ( condición ) { instrucción1 ; instrucción2 ; instrucción3 ; ... }

Hacer ... bucle while

La sintaxis de JavaScript do ... while loopes la siguiente:

hacer { instrucción1 ; instrucción2 ; instrucción3 ; ... } mientras ( condición );

Con

La instrucción `with` agrega todas las propiedades y métodos del objeto dado al ámbito del siguiente bloque, permitiendo que se haga referencia a ellos como si fueran variables locales.

con ( documento ) { const a = getElementById ( 'a' ); const b = getElementById ( 'b' ); const c = getElementById ( 'c' ); };
  • Nótese la ausencia de document. antes de cada invocación de getElementById() .

La semántica es similar a la instrucción `with` de Pascal .

Debido a que la disponibilidad de sentencias `with` dificulta el rendimiento del programa y se cree que reduce la claridad del código (ya que cualquier variable dada podría ser en realidad una propiedad de una sentencia ` with` que la contiene ), esta sentencia no está permitida en modo estricto .

Etiquetas

JavaScript admite etiquetas anidadas en la mayoría de las implementaciones. Los bucles o bloques pueden etiquetarse para la instrucción break, y los bucles para continue. Aunque gotoes una palabra reservada, [ 19 ]goto no está implementada en JavaScript.

loop1 : for ( let a = 0 ; a < 10 ; ++ a ) { if ( a === 4 ) break loop1 ; // Se detiene después del cuarto intento console.log ( ' a = ' + a ); loop2 : for ( let b = 0 ; b < 10 ; ++ b ) { if ( b === 3 ) continue loop2 ; // Se omite el número 3 if ( b === 6 ) continue loop1 ; // Continúa el primer bucle, no se muestra 'finished' console.log ( ' b = ' + b ) ; } // Fin de loop2 console.log ( 'finished' ) ; } // Fin de loop1 block1 : { console.log ( ' Hola' ); // Muestra 'Hola' break block1 ; console.log ( 'Mundo' ) ; // Nunca llegará aquí } goto block1 ; // Error de análisis.

Funciones

Una función es un bloque con una lista de parámetros (posiblemente vacía) que normalmente recibe un nombre. Una función puede usar variables locales. Si el usuario sale de la función sin una instrucción `return`, se devuelve el valor `undefined` .

function gcd ( number1 , number2 ) { if ( isNaN ( number1 * number2 )) throw TypeError ( "Argumentos no numéricos no permitidos." ); number1 = Math . round ( number1 ); number2 = Math . round ( number2 ); let difference = number1 - number2 ; if ( difference === 0 ) return number1 ; return difference > 0 ? gcd ( number2 , difference ) : gcd ( number1 , - difference ); } console . log ( gcd ( 60 , 40 )); // 20//En ausencia de paréntesis después del identificador 'gcd' en el lado derecho de la asignación siguiente, //'gcd' devuelve una referencia a la función misma sin invocarla. let mygcd = gcd ; // mygcd y gcd hacen referencia a la misma función. console.log ( mygcd ( 60 , 40 ) ) ; // 20

Las funciones son objetos de primera clase y pueden asignarse a otras variables.

El número de argumentos que se pasan al llamar a una función no necesariamente coincide con el número de argumentos en la definición de la función; un argumento con nombre en la definición que no tenga un argumento correspondiente en la llamada tendrá el valor `undefined` (que se puede convertir implícitamente a `false`). Dentro de la función, también se puede acceder a los argumentos a través del objeto `arguments` ; esto permite acceder a todos los argumentos mediante índices (por ejemplo, `arguments` ), incluidos aquellos que superan el número de argumentos con nombre. (Si bien la lista de argumentos tiene una propiedad `arguments`, no es una instancia de `Array` ; no tiene métodos como `.slice()` , `.sort()` , etc.).arguments[0],arguments[1],...arguments[n].length

función add7 ( x , y ) { if ( ! y ) { y = 7 ; } console . log ( x + y + arguments . length ); }; add7 ( 3 ); // 11 add7 ( 3 , 4 ); // 9

Los valores primitivos (número, booleano, cadena) se pasan por valor. En el caso de los objetos, se pasa la referencia al objeto.

const obj1 = { a : 1 }; const obj2 = { b : 2 }; function foo ( p ) { p = obj2 ; // Ignora el parámetro real p . b = arguments [ 1 ]; } foo ( obj1 , 3 ); // No afecta a obj1 en absoluto. 3 es un parámetro adicional console . log ( ` ${ obj1 . a } ${ obj2 . b } ` ); // escribe 1 3

Las funciones pueden declararse dentro de otras funciones y acceder a las variables locales de la función externa. Además, implementan cierres completos al conservar las variables locales de la función externa incluso después de que esta haya finalizado.

let t = "Top" ; let bar , baz ; function foo () { let f = "foo var" ; bar = function () { console . log ( f ) }; baz = function ( x ) { f = x ; }; } foo (); baz ( "baz arg" ); bar (); // "baz arg" (no "foo var") aunque foo() haya terminado. console . log ( t ); // Top

Una función anónima es simplemente una función sin nombre y puede escribirse utilizando notación de función o notación de flecha. En estos ejemplos equivalentes, se pasa una función anónima a la función map y se aplica a cada uno de los elementos del array. [ 20 ]

[ 1 , 2 , 3 ]. map ( function ( x ) { return x * 2 ;); //devuelve [2,4,6] [ 1 , 2 , 3 ]. map (( x ) => { return x * 2 ;}); //mismo resultado

Una función generadora se indica colocando un * después de la palabra clave function y contiene una o más instrucciones yield . Su efecto es devolver un valor y pausar la ejecución en el estado actual. Al declarar una función generadora, se devuelve un iterador. Las llamadas posteriores a iterator.next() reanudan la ejecución hasta la siguiente instrucción yield . Cuando el iterador regresa sin usar una instrucción yield, no hay más valores y la propiedad done del iterador se establece en true . [ 21 ]

Con la excepción de los dispositivos iOS de Apple, los generadores no están implementados para navegadores en dispositivos móviles. [ 22 ]

función * generador () { generar "rojo" ; generar "verde" ; generar "azul" ; }let iterador = generador (); let actual ;while ( current = iterator . next (). value ) console . log ( current ); //muestra rojo, verde y luego azul console . log ( iterator . next (). done ) //muestra true

Async/await

El operador `await` en JavaScript (y TypeScript) solo se puede usar dentro de una función asíncrona o en el nivel superior de un módulo . Si el parámetro es una promesa , la ejecución de la función asíncrona se reanudará cuando la promesa se resuelva (a menos que la promesa sea rechazada, en cuyo caso se lanzará un error que se puede manejar con el manejo de excepciones normal de JavaScript ). Si el parámetro no es una promesa, el parámetro en sí se devolverá inmediatamente. [ 23 ]

Muchas bibliotecas proporcionan objetos Promise que también se pueden usar con await, siempre que cumplan con la especificación para promesas nativas de JavaScript. Sin embargo, las promesas de la biblioteca jQuery no eran compatibles con Promises/A+ hasta jQuery 3.0. [ 24 ]

A continuación se muestra un ejemplo (modificado a partir de este artículo [ 25 ] ):

interfaz DBResponse { id : string ; rev? : string ; ok? : boolean ; }Interfaz Documento { _id : cadena ; _rev? : cadena ; [ clave : cadena ] : cualquiera ; }interface Database { post ( doc : object ) : Promise < DBResponse > ; get ( id : string ) : Promise < Document > ; }declarar constante db : Base de datos ;función asíncrona createNewDoc ( ) : Promise <Document> { const response : DBResponse = await db.post ( { } ) ; const doc : Document = await db.get ( response.id ) ; return doc ; }función asíncrona principal () : Promise < void > { try { const doc : Document = await createNewDoc (); console . log ( doc ); } catch ( err : Error ) { console . error ( "Error al crear o obtener el documento:" , err ); } }principal ();

Node.js versión 8 incluye una utilidad que permite usar los métodos basados ​​en devoluciones de llamada de la biblioteca estándar como promesas. [ 26 ]

objetos

Para mayor comodidad, los tipos se subdividen normalmente en primitivos y objetos . Los objetos son entidades que poseen una identidad (solo son iguales a sí mismas) y que asignan nombres de propiedades a valores (o "ranuras" en la terminología de programación basada en prototipos ). Los objetos pueden considerarse como matrices asociativas o hashes, y a menudo se implementan utilizando estas estructuras de datos. Sin embargo, los objetos poseen características adicionales, como una cadena de prototipos , que las matrices asociativas ordinarias no tienen.

JavaScript tiene varios tipos de objetos integrados, a saber Array, Boolean, Date, , Function, Math, Number, Object, RegExpy String. Otros objetos son "objetos anfitriones", definidos no por el lenguaje, sino por el entorno de ejecución. Por ejemplo, en un navegador, los objetos anfitriones típicos pertenecen al DOM (ventana, formulario, enlaces, etc.).

Creación de objetos

Los objetos se pueden crear mediante un constructor o un literal de objeto. El constructor puede usar una función de objeto integrada o una función personalizada. Por convención, las funciones constructoras reciben un nombre que comienza con mayúscula.

// Constructor const anObject = new Object ();// Objeto literal const objectA = {}; const objectA2 = {}; // A != A2, {}s crean nuevos objetos como copias. const objectB = { index1 : 'valor 1' , index2 : 'valor 2' };// Constructor personalizado (ver más abajo)

Los literales de objeto y los literales de matriz permiten crear fácilmente estructuras de datos flexibles:

const myStructure = { name : { first : "Mel" , last : "Smith" }, age : 33 , hobbies : [ "ajedrez" , "correr" ] };

Esta es la base de JSON , que es una notación sencilla que utiliza una sintaxis similar a la de JavaScript para el intercambio de datos.

Métodos

Un método es simplemente una función asignada a una propiedad de un objeto. A diferencia de muchos lenguajes orientados a objetos, en JavaScript no existe distinción entre la definición de una función y la de un método. La distinción se produce durante la llamada a la función; una función puede invocarse como un método.

Cuando se llama como método, la variable local estándar `this` se establece automáticamente al valor de la instancia del objeto a la izquierda del punto ( . ). (También existen métodos `call` y `apply` que pueden establecer `this` explícitamente; algunos paquetes, como jQuery, hacen cosas inusuales con `this` ).

En el ejemplo siguiente, Foo se utiliza como constructor. Un constructor no tiene nada de especial; es simplemente una función que inicializa un objeto. Cuando se usa con la palabra clave new , como es habitual, se le asigna un objeto vacío recién creado.

Nótese que en el ejemplo siguiente, Foo simplemente asigna valores a ranuras, algunas de las cuales son funciones. Por lo tanto, puede asignar diferentes funciones a diferentes instancias. En este ejemplo no se utiliza ningún prototipo.

función px () { return this . prefix + "X" ; }función Foo ( yz ) { this . prefix = "a-" ; if ( yz > 0 ) { this . pyz = function () { return this . prefix + "Y" ; }; } else { this . pyz = function () { return this . prefix + "Z" ; }; } this . m1 = px ; return this ; }const foo1 = new Foo ( 1 ); const foo2 = new Foo ( 0 ); foo2 . prefix = "b-" ;console.log ( " foo1 / 2 " + foo1.pyz ( ) + foo2.pyz ( )); // foo1/ 2 aY bZfoo1 . m3 = px ; // Asigna la función misma, no su resultado evaluado, es decir, no px() const baz = { "prefix" : "c-" }; baz . m4 = px ; // No es necesario un constructor para crear un objeto.console.log ( "m1/m3/m4 " + foo1.m1 ( ) + foo1.m3 ( ) + baz.m4 ( ) ) ; // m1/m3 / m4 aX aX cXfoo1 . m2 (); // Lanza una excepción, porque foo1.m2 no existe.

Constructores

Las funciones constructoras simplemente asignan valores a las ranuras de un objeto recién creado. Estos valores pueden ser datos u otras funciones.

Ejemplo: Manipular un objeto:

función MyObject ( atributoA , atributoB ) { this . atributoA = atributoA ; this . atributoB = atributoB ; }MyObject.staticC = " azul" ; // En la función MyObject, no en el objeto console.log ( MyObject.staticC ) ; // azulconst objeto = nuevo MyObject ( 'rojo' , 1000 );console.log ( object.attributeA ) ; // rojo console.log ( object.attributeB ) ; // 1000console.log ( object.staticC ); // objeto indefinido object.attributeC = new Date ( ) ; // agregar una nueva propiedadeliminar objeto.attributeB ; // elimina una propiedad del objeto // tenga en cuenta que , a diferencia de C++, delete no invoca un "destructor", // sino que elimina una propiedad de un objeto .console.log ( object.attributeB ) ; // indefinido

El constructor en sí se referencia en la ranura del constructor del prototipo del objeto . Por lo tanto,

function Foo () {} // El uso de 'new' establece ranuras de prototipo (por ejemplo, // x = new Foo() establecería el prototipo de x en Foo.prototype, // y Foo.prototype tiene una ranura de constructor que apunta de vuelta a Foo). const x = new Foo (); // Lo anterior es casi equivalente a const y = {}; y . constructor = Foo ; y . constructor (); // Excepto x . constructor == y . constructor ; // true x instanceof Foo ; // true y instanceof Foo ; // false // El prototipo de y es Object.prototype, no // Foo.prototype, ya que se inicializó con // {} en lugar de new Foo. // Aunque Foo se establece en la ranura del constructor de y, // esto es ignorado por instanceof: solo se considera la ranura del constructor del prototipo de y.

Las funciones son objetos en sí mismos, que pueden utilizarse para producir un efecto similar al de las "propiedades estáticas" (según la terminología de C++/Java), como se muestra a continuación. (El objeto función también posee una prototypepropiedad especial, como se explica en la sección "Herencia" más adelante).

La eliminación de objetos rara vez se utiliza, ya que el motor de scripting recolectará la basura de los objetos a los que ya no se hace referencia.

Herencia

JavaScript admite jerarquías de herencia a través de la creación de prototipos al estilo de Self .

En el siguiente ejemplo, la clase Derived hereda de la clase Base . Cuando d se crea como Derived , la referencia a la instancia base de Base se copia a d.base .

Derive no contiene un valor para aBaseFunction , por lo que se recupera de aBaseFunction cuando se accede a aBaseFunction . Esto se hace evidente al cambiar el valor de base.aBaseFunction , lo cual se refleja en el valor de d.aBaseFunction .

Algunas implementaciones permiten acceder al prototipo o establecerlo explícitamente utilizando la ranura __proto__ como se muestra a continuación.

function Base () { this . anOverride = function () { console . log ( "Base::anOverride()" ); };this.aBaseFunction = function () { console.log ( " Base::aBaseFunction() " ) ; } ; }function Derived () { this . anOverride = function () { console . log ( "Derived::anOverride()" ); }; }const base = new Base ( ); Derived.prototype = base ; // Debe estar antes de new Derived() Derived.prototype.constructor = Derived ; // Requerido para que `instanceof` funcioneconst d = new Derived (); // Copia Derived.prototype al slot de prototipo oculto de la instancia d. d instanceof Derived ; // true d instanceof Base ; // truebase . aBaseFunction = function () { console . log ( "Base::aNEWBaseFunction()" ); };d.anOverride ( ); // Derived :: anOverride() d.aBaseFunction ( ) ; // Base :: aNEWBaseFunction( ) console.log ( d.aBaseFunction == Derived.prototype.aBaseFunction ) ; // trueconsole.log ( d .__ proto__ == base ); // verdadero en implementaciones basadas en Mozilla y falso en muchas otras .

A continuación se muestra claramente cómo se copian las referencias a los prototipos al crear una instancia, pero que los cambios en un prototipo pueden afectar a todas las instancias que hacen referencia a él.

función m1 () { return "Uno" ; } función m2 () { return "Dos" ; } función m3 () { return "Tres" ; }función Base () {}Base.prototype.m = m2 ; const bar = new Base ( ); console.log ( " bar.m " + bar.m ( ) ) ; // bar.m Dosfunción Top () { this . m = m3 ; } const t = new Top ();const foo = new Base (); Base.prototype = t ; // No tiene efecto en foo, se copia la *referencia* a t. console.log ( " foo.m " + foo.m ( ) ); // foo.m Dosconst baz = new Base (); console.log ( " baz.m " + baz.m ( ) ); // baz.m Trest.m = m1 ; // Afecta a baz y a cualquier otra clase derivada. console.log ( " baz.m1 " + baz.m ( ) ); // baz.m1 Uno

En la práctica, se utilizan muchas variaciones de estos temas, lo que puede resultar tanto impactante como confuso.

Manejo de excepciones

JavaScript incluye una instrucción try ... catch ... finallypara el manejo de excepciones que permite gestionar los errores en tiempo de ejecución.

La try ... catch ... finallyinstrucción captura las excepciones resultantes de un error o una instrucción throw. Su sintaxis es la siguiente:

try { // Instrucciones en las que podrían lanzarse excepciones } catch ( errorValue ) { // Instrucciones que se ejecutan en caso de excepción } finally { // Instrucciones que se ejecutan posteriormente en cualquier caso }

Inicialmente, se ejecutan las instrucciones dentro del bloque try. Si se produce una excepción, el flujo de control del script pasa inmediatamente a las instrucciones del bloque catch, donde la excepción se utiliza como argumento de error. De lo contrario, se omite el bloque catch. Este bloque puede lanzar `throw(errorValue) ` si no desea gestionar un error específico.

En cualquier caso, las instrucciones del bloque finally siempre se ejecutan. Si bien la memoria se libera automáticamente, esto puede utilizarse para limpiar manualmente los recursos (como cerrar archivos o conexiones).

Se puede omitir la cláusula catch o la cláusula finally. El argumento catch es obligatorio.

La implementación de Mozilla permite múltiples sentencias catch, como una extensión del estándar ECMAScript. Siguen una sintaxis similar a la utilizada en Java :

try { instrucción ; } catch ( e if e == "InvalidNameException" ) { instrucción ; } catch ( e if e == "InvalidIdException" ) { instrucción ; } catch ( e if e == "InvalidEmailException" ) { instrucción ; } catch ( e ) { instrucción ; } finally { instrucción ; }

En un navegador, el evento onerror se utiliza con mayor frecuencia para capturar excepciones.

onerror = function ( errorValue , url , lineNr ) {...; return true ;};

Funciones y métodos nativos

evaluar (expresión)

Evalúa el primer parámetro como una expresión, que puede incluir sentencias de asignación. Se puede hacer referencia a variables locales de las funciones mediante la expresión. Sin embargo, evalrepresenta un grave riesgo de seguridad, ya que permite que un atacante ejecute código arbitrario, por lo que se desaconseja su uso. [ 27 ]

> ( función foo () { ... var x = 7 ; ... console . log ( "val " + eval ( "x + 2" )); ... })(); val 9 indefinido

Características específicas de TypeScript

TypeScript , un superconjunto de JavaScript desarrollado por Microsoft , añade las siguientes extensiones de sintaxis a JavaScript:

Sintácticamente, TypeScript es muy similar a JScript .NET , otra implementación de Microsoft del estándar de lenguaje ECMA-262 que añadió soporte para tipado estático y características clásicas de lenguajes orientados a objetos como clases, herencia, interfaces y espacios de nombres. Otras fuentes de inspiración son Java y C# .

Anotaciones de tipo

TypeScript proporciona tipado estático mediante anotaciones de tipo para permitir la comprobación de tipos en tiempo de compilación .

función agregar ( izquierda : número , derecha : número ) : número { return izquierda + derecha ; }

Los tipos primitivos se anotan usando tipos en minúsculas, como number, boolean, bigint, y string. Estos tipos son distintos de sus contrapartes encapsuladasNumber ( , Boolean, etc.), que no pueden tener operaciones realizadas directamente sobre valores (un Numbery numberno se pueden sumar). Además, existen tipos undefinedy nullpara sus respectivos valores.

Todos los demás tipos no primitivos se anotan usando su nombre de clase, como Error. Los arreglos se pueden escribir de dos maneras diferentes que son sintácticamente iguales: la sintaxis basada en genéricos Array<T>y una forma abreviada con T[].

Los tipos de datos integrados adicionales son tuplas, uniones, never, unknown, void, y any:

  • Una matriz con tipos de datos predefinidos en cada índice es una tupla, representada como [type1, type2, ..., typeN].
  • Una variable que puede contener más de un tipo de datos es una unión, representada mediante el |símbolo lógico OR ( string | number).
  • Este nevertipo se utiliza cuando un tipo determinado debería ser imposible de crear, lo cual resulta útil para filtrar tipos mapeados.
  • Este unknowntipo se utiliza al trabajar con datos de forma impredecible. A diferencia de any, una unknownvariable de tipo generará errores de compilación al intentar acceder a propiedades o métodos de dicha variable sin antes determinar su tipo. Este tipo se utiliza a menudo para capturar errores, gestionar respuestas de API o entradas de usuario. [ 29 ]
  • El voidtipo se utiliza para representar la ausencia de un tipo, por ejemplo, de una función sin ninguna returndeclaración.
  • Un valor de tipo anyadmite las mismas operaciones que un valor en JavaScript y se realiza una comprobación de tipo estática mínima, [ 30 ] lo que lo hace adecuado para estructuras con tipado débil o dinámico. Esta práctica generalmente se desaconseja y debe evitarse siempre que sea posible. [ 31 ]

Las anotaciones de tipo se pueden exportar a un archivo de declaraciones independiente para que la información de tipo esté disponible para los scripts de TypeScript que utilizan tipos ya compilados en JavaScript. Las anotaciones se pueden declarar para una biblioteca JavaScript existente, como se ha hecho para Node.js y jQuery .

El compilador de TypeScript utiliza la inferencia de tipos cuando no se proporcionan tipos. Por ejemplo, el addmétodo en el código anterior se inferiría que devuelve un numberincluso si no se hubiera proporcionado ninguna anotación de tipo de retorno. Esto se basa en que los tipos estáticos de lefty rightson number, y en el conocimiento del compilador de que el resultado de sumar dos numbersiempre es un number.

Si no se puede inferir ningún tipo debido a la falta de declaraciones (como en un módulo JavaScript sin tipos), entonces se utiliza por defecto el anytipo dinámico. Se pueden proporcionar tipos de módulo adicionales mediante un archivo de declaración .d.ts utilizando la declare module "moduleName"sintaxis.

Archivos de declaración

Cuando se compila un script de TypeScript, existe la opción de generar un archivo de declaración (con la extensión .txt .d.ts) que funciona como interfaz para los componentes del JavaScript compilado. En este proceso, el compilador elimina los cuerpos de las funciones y los métodos, conservando únicamente las firmas de los tipos exportados. El archivo de declaración resultante puede utilizarse para describir los tipos virtuales de TypeScript exportados de una biblioteca o módulo de JavaScript cuando un desarrollador externo lo utiliza desde TypeScript.

El concepto de archivos de declaración es análogo al concepto de archivos de cabecera que se encuentra en C/C++ .

declare namespace Arithmetics { add ( left : number , right : number ) : number ; subtract ( left : number , right : number ) : number ; multiply ( left : number , right : number ) : number ; divide ( left : number , right : number ) : number ; }

Los archivos de declaración de tipos se pueden escribir manualmente para las bibliotecas JavaScript existentes, como ya se ha hecho para jQuery y Node.js.

En GitHub, en DefinitelyTyped , se encuentran alojadas grandes colecciones de archivos de declaración para bibliotecas JavaScript populares .

Medicamentos genéricos

TypeScript admite programación genérica utilizando una sintaxis similar a la de Java . [ 32 ] El siguiente es un ejemplo de la función identidad . [ 33 ]

función identidad < T > ( x : T ) : T { return x ; }

De forma similar a los genéricos de Java , es posible vincular un parámetro de tipo:

función f < T extiende cadena > ( x : T ) : void { // ... }function prop < T , K extends keyof T > ( obj : T , key : K ) : T [ K ] { return obj [ key ]; }

Además, al igual que en C++, es posible tener parámetros genéricos predeterminados.

función makeArray < T = número > ( valor : T ) : T [] { return [ valor ]; }

Clases

TypeScript utiliza el mismo estilo de anotación para métodos y campos de clase que para funciones y variables, respectivamente. En comparación con las clases JavaScript estándar, una clase TypeScript también puede implementar una interfaz mediante la implementspalabra clave, usar parámetros genéricos de forma similar a Java y especificar campos públicos y privados.

clase Persona { nombre público : cadena ; edad privada : número ; salario privado : número ;constructor ( nombre : cadena , edad : número , salario : número ) { this . nombre = nombre ; this . edad = edad ; this . salario = salario ; }toString ( ) : string { return ` $ { this.name } ( $ { this.age } ) ( $ { this.salary } ) ` ; } }

Tipos de sindicatos

TypeScript admite tipos de unión. [ 34 ] El lenguaje etiqueta implícitamente los valores con un tipo y puede recuperarlos mediante una typeofllamada para valores primitivos y una instanceofcomparación para tipos de datos complejos. Los tipos con usos superpuestos (por ejemplo, un método slice existe tanto en cadenas como en matrices, el operador plus funciona tanto en cadenas como en números) no necesitan una restricción adicional para usar estas características.

función sucesor ( n : número | bigint ) : número | bigint { // los tipos que admiten las mismas operaciones no necesitan estrechamiento return ++ n ; }function dependsOnParameter ( v : string | string [] | number ) { // Los tipos distintos necesitan ser restringidos if ( v instanceof Array ) { // hacer algo } else if ( typeof ( v ) === "string" ) { // hacer otra cosa } else { // Tiene que ser un número } }

Tipos enumerados

TypeScript añade un tipo de datos 'enum' a JavaScript.

enum CardSuit { Clubs , Diamonds , Hearts , Spades };var c : CardSuit = CardSuit . Diamonds ;

Por defecto, los enumeradores numeran sus miembros comenzando en 0; esto se puede anular estableciendo el valor del primero:

enum CardSuit { Clubs = 1 , Diamonds , Hearts , Spades };var c : CardSuit = CardSuit . Diamonds ;

Todos los valores se pueden configurar:

enum CardSuit { Clubs = 1 , Diamonds = 2 , Hearts = 4 , Spades = 8 };var c : CardSuit = CardSuit . Diamonds ;

TypeScript admite la asignación de un valor numérico a su nombre. Por ejemplo, esto encuentra el nombre del valor 2:

enum CardSuit { Clubs = 1 , Diamonds , Hearts , Spades };var suitName : string = CardSuit [ 2 ];alerta ( trajeName );

Módulos y espacios de nombres

TypeScript distingue entre módulos y espacios de nombres, de forma similar a los módulos de C++ . Ambas características de TypeScript permiten encapsular clases, interfaces, funciones y variables en contenedores. Los espacios de nombres (anteriormente módulos internos) utilizan expresiones de funciones JavaScript invocadas inmediatamente para encapsular código, mientras que los módulos (anteriormente módulos externos) utilizan patrones de bibliotecas JavaScript existentes ( CommonJS o módulos ES). [ 35 ]

Gestión de recursos

Aunque TypeScript no tiene gestión manual de memoria, sí tiene gestión de recursos similar a usinglos bloques `with-resource` en C# o try`with-resources` en Java , o a la adquisición de recursos en la inicialización de C++ , que cierran automáticamente los recursos sin necesidad de bloques. En TypeScript, para cerrar automáticamente un objeto, este debe implementar una interfaz global y un método . Este método se llamará automáticamente al final del ámbito. [ 28 ]finallyDisposableSymbol.dispose()

import * as fs from 'fs' ;clase TempFile implementa Disposable { #path : string ; #handle : number ;constructor ( ruta : cadena ) { this . #ruta = ruta ; this . #manejo = fs . openSync ( ruta , "w+" ); }escribir ( datos : cadena ) : void { fs . writeSync ( this . #handle , datos ); }[ Símbolo . dispose ]() : void { fs . closeSync ( this . #handle ); fs . unlinkSync ( this . #path ); } }export function doSomeWork () { using file : TempFile = new TempFile ( ".some_temp_file.txt" );if ( algunaCondición ()) { // hacer algo aquí } }

Véase también

Referencias

  1. "Especificación de JavaScript 1.1" . Archivado del original el 26 de febrero de 2017. Consultado el 19 de abril de 2006 .
  2. "Capítulo 1. JavaScript básico" . speakingjs.com . Archivado del original el 10 de febrero de 2022. Consultado el 22 de septiembre de 2020 .
  3. Flanagan, David (2006). JavaScript: La guía definitiva . O'Reilly Media, Inc. pág . 16. ISBN  978-0-596-10199-2Omitir los puntos y comas no es una buena práctica de programación; deberías acostumbrarte a insertarlos.
  4. Farias, Bradley. "Gramática Hashbang" . GitHub . Consultado el 13 de julio de 2025 .
  5. "Almacenar la información que necesitas: Variables - Aprende desarrollo web | MDN" . developer.mozilla.org . 9 de mayo de 2023. Consultado el 23 de junio de 2023 .
  6. "Valores, variables y literales - MDC" . Mozilla Developer Network. 16 de septiembre de 2010. Archivado del original el 29 de junio de 2011. Consultado el 1 de febrero de 2020 .
  7. "JavaScript Hoisting" . W3Schools . Archivado del original el 31 de marzo de 2022. Consultado el 17 de diciembre de 2021. En JavaScript, una variable puede declararse después de haber sido utilizada. En otras palabras, una variable puede utilizarse antes de haber sido declarada.
  8. " JavaScript Scoping and Hoisting Archivado el 8 de mayo de 2021 en Wayback Machine ", Ben Cherry Archivado el 28 de febrero de 2021 en Wayback Machine , Adequately Good Archivado el 8 de marzo de 2022 en Wayback Machine , 8 de febrero de 2010
  9. La edición 5e de ECMA-262 aclaró este comportamiento con el Registro de Entorno Declarativo y el Registro de Entorno de Objeto . Con este formalismo, el objeto global es el Registro de Entorno de Objeto del Entorno Léxico global (el ámbito global ).
  10. "Número - JavaScript" . MDN Web Docs . Consultado el 13 de julio de 2025 .
  11. 1 2 "BigInt - Javascript" . MDN Web Docs . Consultado el 13 de julio de 2025 .
  12. "Literales de plantilla" . MDN Web Docs . Archivado del original el 31 de marzo de 2022. Consultado el 4 de noviembre de 2023 .
  13. "Operadores de comparación - Centro de documentación de MDC" . Mozilla. 5 de agosto de 2010. Archivado del original el 4 de mayo de 2012. Consultado el 5 de marzo de 2011 .
  14. "Los elementos del estilo JavaScript" . Douglas Crockford. Archivado del original el 17 de marzo de 2011. Consultado el 5 de marzo de 2011 .
  15. Orendorff, Jason. "ES6 en profundidad: símbolos" . Mozilla Hacks . Consultado el 13 de julio de 2025 .
  16. "Sintaxis de propagación (...) - JavaScript | MDN" . developer.mozilla.org . 25 de septiembre de 2023.
  17. "parámetros de reposo" . 9 de septiembre de 2024. Archivado del original el 30 de mayo de 2018. Recuperado el 29 de septiembre de 2016 .
  18. "Especificación del lenguaje ECMAScript 2020" . Ecma International . Junio ​​de 2020.
  19. ECMA-262, Edición 3, 7.5.3 Palabras reservadas del futuro
  20. Yadav, Amitya (4 de octubre de 2024). "Impactos de las funciones con nombre frente a las funciones anónimas" . medium.com . Consultado el 19 de febrero de 2025 .
  21. "función*" . Documentación web de mdm . Consultado el 23 de febrero de 2025 .
  22. "Generadores ES6" . medium.com . Consultado el 23 de febrero de 2025 .
  23. "await - JavaScript (MDN)" . Consultado el 2 de mayo de 2017 .
  24. "Guía de actualización de jQuery Core 3.0" . Consultado el 2 de mayo de 2017 .
  25. "Domando a la bestia asíncrona con ES7" . Consultado el 12 de noviembre de 2015 .
  26. Fundación, Node.js (30 de mayo de 2017). " Node v8.0.0 (actual) - Node.js" . Node.js.
  27. "eval()" . MDN Web Docs . Archivado del original el 1 de abril de 2022. Consultado el 29 de enero de 2020 .
  28. 1 2 "Documentación – TypeScript 5.2" . www.typescriptlang.org . Archivado del original el 9 de agosto de 2024. Recuperado el 9 de noviembre de 2023 .
  29. "Manual - Tipos básicos" . www.typescriptlang.org . Consultado el 2 de julio de 2025 .
  30. "Especificación del lenguaje TypeScript, pág. 24" (PDF) . Archivado del original (PDF) el 17 de noviembre de 2013.
  31. "TypeScript: Documentación – Tipos cotidianos" . www.typescriptlang.org/ . Archivado del original el 9 de agosto de 2024. Consultado el 30 de marzo de 2021 .
  32. Turner, Jonathan (18 de junio de 2013). "Anuncio de TypeScript 0.9" . Blog del equipo del lenguaje TypeScript . Microsoft . Archivado del original el 26 de noviembre de 2013. Consultado el 18 de junio de 2013 .
  33. "Genéricos en Typescript" . Microsoft . Archivado del original el 5 de abril de 2020. Consultado el 8 de abril de 2020 .
  34. "Manual - Uniones y tipos de intersección" . www.typescriptlang.org . Consultado el 30 de noviembre de 2020 .
  35. Sothmann, Sönke (31 de enero de 2014). "Una introducción al sistema de módulos de TypeScript" . blog.oio.de. Archivado del original el 1 de febrero de 2014. Recuperado el 21 de febrero de 2014 .

Lecturas adicionales

  • Danny Goodman: La Biblia de JavaScript , Wiley, John & Sons, ISBN 0-7645-3342-8.
  • David Flanagan, Paula Ferguson: JavaScript: La guía definitiva , O'Reilly & Associates, ISBN 0-596-10199-6.
  • Thomas A. Powell, Fritz Schneider: JavaScript: La referencia completa , McGraw-Hill Companies, ISBN 0-07-219127-9.
  • Axel Rauschmayer: Hablando JavaScript: Una guía exhaustiva para programadores , 460 páginas, O'Reilly Media, 25 de febrero de 2014, ISBN 978-1449365035( Edición gratuita en línea )
  • Emily Vander Veer: JavaScript para principiantes, 4.ª edición , Wiley, ISBN 0-7645-7659-3.
  • Introducción a JavaScript - Centro para desarrolladores de Mozilla
  • Bucles de JavaScript
  • Referencias del estándar ECMAScript: ECMA-262
  • Lecciones interactivas de JavaScript: basadas en ejemplos.
  • Formación en JavaScript
  • Referencias principales del Centro para desarrolladores de Mozilla para las versiones 1.5 , 1.4 , 1.3 y 1.2 de JavaScript.
  • Documentación del lenguaje JavaScript de Mozilla
Obtenido de " https://en.wikipedia.org/w/index.php?title=JavaScript_syntax&oldid=1362175469 "