stringtranslate.com

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 correctamente estructurado.

Los ejemplos a continuación utilizan la función de registro del objeto de consola 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 creación de scripts del lado del cliente en los navegadores web modernos , y que casi todos los navegadores web proporcionan la función de alerta, alerttambién se puede utilizar , pero no se utiliza habitualmente.

Orígenes

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.

Lo esencial

Sensibilidad a mayúsculas y minúsculas

JavaScript distingue entre mayúsculas y minúsculas . Es habitual empezar el nombre de un constructor con una letra mayúscula y el nombre 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 comas terminan las sentencias en JavaScript. Debido a la inserción automática de puntos y comas (ASI), algunas sentencias que están bien formadas cuando se analiza una nueva línea se considerarán completas, como si se hubiera insertado un punto y coma justo antes de la nueva línea. Algunas autoridades recomiendan proporcionar puntos y comas de finalización de sentencias de forma explícita, porque puede reducir los efectos no deseados de la inserción automática de puntos y comas. [3]

Hay dos problemas: cinco tokens pueden comenzar 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 potencialmente produce un análisis incorrecto.

Los cinco símbolos problemáticos son el paréntesis de apertura " (", el corchete de apertura " [", la barra " /", 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 , y el corchete de apertura aparece a veces, mientras que otras veces son bastante raras. Un ejemplo:

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

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

Algunos sugieren en cambio el uso de punto y coma inicial en las líneas que comienzan con ' (' o ' [', de modo que la línea no se una accidentalmente con la anterior. Esto se conoce como punto y coma defensivo y se recomienda especialmente, porque de lo contrario el código puede volverse ambiguo al reorganizarse. Por ejemplo:

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

Los puntos y coma iniciales también se utilizan a veces al comienzo de las bibliotecas de JavaScript, en caso de que se agreguen a otra biblioteca que omite un punto y coma final, ya que esto puede generar ambigüedad en la declaración inicial.

Las cinco producciones restringidas son return, throw, break, continue, y post-incremento/decremento. En todos los casos, insertar punto y coma no soluciona el problema, pero aclara la sintaxis analizada, lo que hace que el error sea más fácil de detectar. returny throwtoman un valor opcional, mientras que breaky continuetoman una etiqueta opcional. En todos los casos, el consejo es mantener el valor o la etiqueta en la misma línea que la declaración. Esto aparece con mayor frecuencia en la declaración de retorno, donde uno 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.

devuelve a + b ;  // Devuelve indefinido. Se trata como: // return; // a + b; // Debe escribirse como: // return a + b;

Comentarios

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

// un comentario breve de una línea/* Este es un comentario largo de varias líneas  sobre mi guión. Ojalá algún día  sea genial. *//* Los comentarios /* no pueden estar anidados */ Error de sintaxis * /   

Variables

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

A partir de JavaScript 1.5, se pueden utilizar letras ISO 8859-1 o Unicode (o \uXXXXsecuencias de escape Unicode) en identificadores. [5] En ciertas implementaciones de JavaScript, se puede utilizar el signo arroba (@) en un identificador, pero esto es contrario a las especificaciones y no se admite en implementaciones más nuevas. [ cita requerida ]

Detección 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, se puede asignar una variable y usarla antes de declararla en el código. [6] Esto se conoce comoelevación , y es equivalente a que las variables sedeclaren hacia adelanteen la parte superior de la función o bloque.[7]

Con las instrucciones var, let, y const, solo se eleva la declaración; las asignaciones no se elevan. Por lo tanto, una instrucción en el medio de la función es equivalente a una instrucción de declaración en la parte superior de la función y una instrucción de asignación en ese punto en el medio de la función. Esto significa que no se puede acceder a los valores antes de que se declaren; la referencia hacia adelante no es posible. Con el valor de una variable es hasta que se inicializa. No se puede acceder a las variables declaradas con o hasta que se hayan inicializado, por lo que hacer referencia a dichas variables antes provocará un error.var x = 1var xx = 1varundefinedletconst

Las declaraciones de función, que declaran una variable y le asignan una función, son similares a las declaraciones de variable, pero además de elevar la declaración, también elevan la asignación (como si la declaración completa apareciera en la parte superior de la función que la contiene) y, por lo tanto, también es posible la referencia hacia adelante: la ubicación de una declaración de función dentro de una función que la encierra es irrelevante. Esto es diferente de una expresión de función que se asigna a una variable en una declaración var, leto const.

Así, por ejemplo,

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

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

Declaración y cesión

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

Cuando JavaScript intenta resolver un identificador, busca en el ámbito local. Si no encuentra este identificador, 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 sigue sin encontrarlo, JavaScript generará una ReferenceErrorexcepción.

Al asignar un identificador, JavaScript pasa por exactamente el mismo proceso para recuperar este identificador, excepto que si no se encuentra en el ámbito global , creará la "variable" en el ámbito donde fue creada. [8] Como consecuencia, una variable nunca declarada será global, si se 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 (generalmente window ) también creará una nueva variable global.

Tenga en cuenta 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

A continuación se muestran algunos ejemplos de declaraciones de variables y alcance:

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 bloque        función f () { var z = 'zorros' , r = 'pájaros' ; // 2 variables locales m = 'peces' ; // global, porque no se declaró en ningún lugar antes               función hija () { var r = 'monos' ; // Esta variable es local y no afecta a los "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 utilizar en cualquier parte de la función, incluso antes, como aquí var veinte ;      niño (); devolver 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 
para ( 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: Asignación a variable constante          for ( const i of [ 1 , 2 , 3 ]) console . log ( i ); //no lanzará una excepción. i no se reasigna sino que se vuelve a crear en cada iteración      const pi ; // arroja un SyntaxError: Falta inicializador en la declaración const  

Tipos de datos primitivos

El lenguaje JavaScript proporciona seis tipos de datos primitivos :

Algunos de los tipos de datos primitivos también proporcionan un conjunto de valores con nombre que representan la extensión de los límites del tipo. 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 cuando se comprueban propiedades de objetos que no existen. En un contexto booleano, el valor "undefined" se considera un valor falso.

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

let test ; // variable declarada, pero no definida, ... // ... establecida en valor indefinido const testObj = {}; console . log ( test ); // variable de prueba existe, pero valor no ... // ... definido, muestra indefinido console . log ( testObj . myProp ); // testObj existe, propiedad no, ... // ... muestra indefinido console . log ( undefined == null ); // tipo no aplicado durante la comprobación, muestra verdadero console . log ( undefined === null ); // tipo aplicado durante la comprobación, muestra falso                

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

Funciones como ésta no funcionarán como se espera:

function isUndefined ( x ) { sea u ; return x === u ; } // así... function isUndefined ( x ) { return x === void 0 ; } // ... o esa segunda function isUndefined ( x ) { return ( typeof x ) === "undefined" ; } // ... o esa tercera                            

Aquí, al llamar isUndefined(my_var)se genera un ReferenceError si my_var es un identificador desconocido, mientras que no lo hace.typeof my_var === 'undefined'

Número

Los números se representan en binario como dobles de punto flotante IEEE 754. Aunque este formato proporciona 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 falso console.log ( 0.94 - 0.01 ) ; // muestra 0.9299999999999999        

Como resultado, se debe utilizar una rutina como el método toFixed() para redondear números siempre que se formatean para la 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 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, dígitos representados por las ... // ... letras AF pueden ser mayúsculas o minúsculas       

También hay un separador numérico, _ (el guión bajo), introducido en ES2021:

// Nota: La sintaxis de Wikipedia aún no admite separadores numéricos 1 _000_000_000 ; // Se utiliza con números grandes 1 _000_000 .5 ; // Se admite con decimales 1 _000e1_000 ; // Se admite con exponentes   // Soporte para binarios, octales y hexadecimales 0b0000 _0000_0101_1011 ; 0o0001 _3520_0237_1327 ; 0xFFFF _FFFF_FFFF_FFFE ;// Pero no puedes usarlos al lado de una parte de número que no sea un dígito, o al principio o al final _12 ; // La variable no está definida (el guión 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 al lado del punto decimal) 12. _0 ; // Error de sintaxis 12 e_6 ; // Error de sintaxis (al lado de "e", un no-dígito. No tiene sentido poner un separador al principio) 1000 ____0000 ; // Error de sintaxis (al lado de "_", un no-dígito. Solo se permite 1 separador a la vez      

Las extensiones +∞ , −∞ y NaN (Not a Number) del tipo número se pueden obtener mediante dos expresiones de programa:

Infinito ; // infinito positivo (el negativo se obtiene con -Infinity, por ejemplo) NaN ; // El valor No-Un-Número, 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 corresponden y se comportan como los describe el IEEE-754 .

El constructor Number (usado como función), o un unario + o -, se puede utilizar para realizar una conversión numérica explícita:

const miCadena = "123.456" ; const miNumero1 = Número ( miCadena ); const miNumero2 = + miCadena ;         

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

const myNumericWrapper = nuevo Número ( 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               // Puede utilizar 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    

Gran int

Los BigInts se pueden utilizar para números enteros arbitrariamente grandes . Especialmente números enteros mayores que 2 53 - 1, que es el número más grande que JavaScript puede representar de manera confiable con el primitivo Number y representado por la constante Number.MAX_SAFE_INTEGER.

Al dividir BigInts, los resultados se truncan .

Cadena

Una cadena en JavaScript es una secuencia de caracteres. En JavaScript, 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 nueva línea escapados (como \n). El estándar de JavaScript permite el carácter de comilla invertida (`, también conocido como acento grave o tilde invertido) para citar cadenas literales de varias líneas, así como literales de plantilla, que permiten la interpolación de expresiones evaluadas con conversión de tipo dentro de una cadena. [9]

const greeting = "¡Hola, mundo!" ; const anotherGreeting = 'Saludos, gente de la Tierra.' ; const aMultilineGreeting = `Saludos cordiales, John Doe.`         // Los literales de plantilla convierten el tipo de expresiones evaluadas en interpolaciones y las hacen iguales 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.'    

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

const h = saludo . charAt ( 0 );   

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

const h = saludo [ 0 ];   

Sin embargo, las cadenas de JavaScript son inmutables :

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

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

const x = "Mundo" ; const compare1 = ( "Hola, " + x == "Hola, Mundo" ); // Aquí compare1 contiene verdadero. const compare2 = ( "Hola, " + x == "Hola, Mundo" ); // Aquí compare2 contiene ... // ... falso ya que los ... // ... primeros caracteres ... // ... de ambos operandos ... // ... no son del mismo caso.                       

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

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

El constructor de cadena crea un objeto de cadena (un objeto que envuelve una cadena):

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

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

const s = new String ( "Hola!" ); typeof s ; // Es 'objeto'. typeof s . valueOf (); // Es 'cadena'.        

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

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

Booleano

JavaScript proporciona un tipo de datos booleano con literales verdaderos y falsos . 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 tipos

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

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

Número y cadena
La cadena se convierte en un valor numérico. JavaScript intenta convertir el literal numérico de cadena en un valor de tipo Número. Primero, se deriva un valor matemático del literal numérico de cadena. A continuación, este valor se redondea al valor de tipo Número más cercano.
Booleano
Si uno de los operandos es un booleano, el operando booleano se convierte a 1 si es verdadero , o a 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. El objeto se convierte en un valor de cadena o número primitivo mediante los métodos .valueOf() o .toString() del objeto. Si esto falla, se genera un error de tiempo de ejecución.

Conversión de tipo booleano

Douglas Crockford defiende los términos "truthy" y "falsy" para describir cómo se comportan los valores de varios tipos cuando se evalúan en un contexto lógico, especialmente en relación con los casos extremos. [11] 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 : false , en el caso de la conjunción : ( ), o true , en el caso de la disyunción : ( ); de lo contrario, se devuelve el operando derecho. La coerción de tipo automática por parte de los operadores de comparación puede diferir para los casos de operandos mixtos booleanos y compatibles con números (incluidas las cadenas que se pueden evaluar como un número u objetos que se pueden evaluar como una cadena de este tipo), porque el operando booleano se comparará como un valor numérico. Esto puede ser inesperado. Una expresión se puede convertir explícitamente a un primitivo booleano duplicando el operador de negación lógica : ( !! ), utilizando la función Boolean() o utilizando el operador condicional : ( ).a && ba || bc ? t : f

// Coerción de tipo automática console.log ( true == 2 ) ; // falso... verdadero → 1 !== 2 ← 2 console.log ( false == 2 ) ; // falso... falso → 0 !== 2 ← 2 console.log(true == 1); // verdadero.... verdadero → 1 === 1 ← 1 console.log( false == 0 ) ; // verdadero .... falso 0 === 0 0 console.log ( true == " 2 " ) ; // falso ... verdadero → 1 !== 2 ← "2" console.log ( false == "2" ); // falso ... falso → 0 ! == 2 ← "2" console.log ( true == " 1" ); // verdadero.... verdadero → 1 === 1 ← "1" console.log ( falso == " 0" ); // verdadero.... falso → 0 === 0 ← "0" console.log ( falso == " " ) ; // verdadero .... falso → 0 === 0 ← "" console.log ( falso == NaN ) ; // falso... falso → 0 !== NaN                                   console . log ( NaN == NaN ); // falso...... NaN no es equivalente a nada, incluido NaN.   // Comparación de tipo comprobado (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 valores coinciden console.log ( true === !! 0 ) ; // falso ... los tipos de datos coinciden, pero los valores difieren console.log ( 1 ? true : false ); // verdadero... solo ±0 y NaN son números "falsos" console.log ( "0" ? true : false ); // verdadero ... solo la cadena vacía es "falsa" console.log ( Boolean ( {})); // verdadero... todos los objetos son " veraces "                  

El operador new se puede utilizar para crear un contenedor de objeto para un primitivo booleano. Sin embargo, el operador typeof no devuelve boolean para el contenedor de objeto, sino que devuelve object . Debido a que todos los objetos se evalúan como true , se debe utilizar un método como .valueOf() o .toString() para recuperar el valor encapsulado. Para la conversión explícita al tipo booleano, Mozilla recomienda que se utilice la función Boolean() (sin new ) en lugar del objeto booleano.

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 ()); // Preferido                      si ( 0 || - 0 || "" || null || indefinido || b . valueOf () || ! new Boolean () || ! t ) { console . log ( "Nunca esto" ); } de lo contrario si ([] && {} && b && typeof b === "object" && b . toString () === "false" ) { console . log ( "Siempre esto" ); }                                    

Símbolo

Novedad en ECMAScript6: un símbolo es un identificador único e inmutable.

Ejemplo:

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

También hay símbolos bien conocidos .

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

const x = [ 1 , 2 , 3 , 4 ]; // x es una matriz x [ Símbolo . iterador ] === Matriz . prototipo [ Símbolo . iterador ]; // y las matrices son iterables          const xIterator = x [ Symbol . iterator ](); // La función [Symbol.iterator] debe proporcionar un iterador para x xIterator . next (); // { valor: 1, hecho: falso } xIterator . next (); // { valor: 2, hecho: falso } xIterator . next (); // { valor: 3, hecho: falso } xIterator . next (); // { valor: 4, hecho: falso } xIterator . next (); // { valor: indefinido, hecho: verdadero } xIterator . next (); // { valor: indefinido, hecho: verdadero }          // 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: [ Símbolo . iterador ] en Conjunto . prototipo ; // verdadero   para ( const valor de nuevo Set ([ 'manzana' , 'naranja' ])) { console . log ( valor ); // "manzana" "naranja" }         

Objetos nativos

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

Formación

Un array es un objeto de JavaScript cuyo prototipo se obtiene a partir del Arrayconstructor, diseñado específicamente para almacenar valores de datos indexados por claves enteras. Los arrays, a diferencia del tipo Object básico, se construyen con métodos y propiedades para ayudar al programador en tareas rutinarias (por ejemplo, join, slicey push).

Al igual que en la familia C , las matrices utilizan un esquema de indexación basado en cero: un valor que se inserta en una matriz vacía mediante el pushmétodo ocupa el índice 0 de la matriz.

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");       

Las matrices tienen una lengthpropiedad que garantiza que siempre será mayor que el índice entero más grande utilizado en la matriz. Se actualiza automáticamente si se crea una propiedad con un índice aún mayor. Si se escribe un número menor en la lengthpropiedad, se eliminarán los índices mayores.

Se puede acceder a los elementos de Arrays utilizando la notación de acceso a propiedades de objetos normal:

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

Los dos ejemplos 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 una matriz puede utilizar un Arrayliteral o el Arrayconstructor:

deje miArray ; // Literales de matriz myArray = [ 1 , 2 ]; // longitud de 2 myArray = [ 1 , 2 ,]; // misma matriz - También puedes tener una coma adicional al final        // También es posible no rellenar partes de la matriz myArray = [ 0 , 1 , /* agujero */ , /* agujero */ , 4 , 5 ]; // longitud de 6 myArray = [ 0 , 1 , /* agujero */ , /* agujero */ , 4 , 5 ,]; // misma matriz myArray = [ 0 , 1 , /* agujero */ , /* agujero */ , 4 , 5 , /* agujero */ ,]; // longitud de 7                         // Con el constructor myArray = new Array ( 0 , 1 , 2 , 3 , 4 , 5 ); // longitud de 6 myArray = new Array ( 365 ); // una matriz vacía con longitud 365             

Las matrices se implementan de modo que solo los elementos definidos utilicen memoria; son " matrices dispersas ". La configuración y solo utiliza espacio para estos dos elementos, al igual que cualquier otro objeto. El de la matriz se seguirá informando como 58. La longitud máxima de una matriz es 4.294.967.295, que corresponde a un número binario de 32 bits (1111111111111111111111111111111111) 2 .myArray[10] = 'someThing'myArray[57] = 'somethingOther'length

Se puede utilizar el literal de declaración de objeto para crear objetos que se comporten de manera muy similar a las matrices asociativas en otros lenguajes:

const dog = { color : "brown" , size : "large" }; dog [ "color" ]; // da como resultado "brown" dog . color ; // también da como resultado "brown"        

Se pueden utilizar los literales de declaración de objetos y matrices para crear rápidamente matrices que sean asociativas, multidimensionales o ambas. (Técnicamente, JavaScript no admite matrices multidimensionales, pero se pueden imitar con matrices de matrices).

const gatos = [{ color : "marrón" , tamaño : "grande" }, { color : "negro" , tamaño : "pequeño" }]; gatos [ 0 ][ "tamaño" ]; // da como resultado "grande"           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 recuento de milisegundos con signo, donde cero representa el 1970-01-01 00:00:00 UT y un rango de ±10 8 días. Hay varias formas de proporcionar argumentos al Dateconstructor. Tenga en cuenta que los meses se basan en cero.

new Date (); // crea una nueva instancia de Date que represente la fecha/hora actual. new Date ( 2010 , 2 , 1 ); // crea una nueva instancia de Date que represente 2010-Mar-01 00:00:00 new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // crea una nueva instancia de Date que represente 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 un útil toString:

const d = nueva Fecha ( 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 toString incorporado devuelve algo como 'Lun 01 Mar 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." );  

Estos pueden detectarse mediante 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 o grados centesimales .

Expresión regular

/expresión/ . test ( cadena ); // devuelve el valor booleano "cadena" . search ( /expresión/ ); // devuelve la posición Número "cadena" . replace ( /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 sea de // - - 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 - CR // . - cualquier carácter // | - Osi ( /Tm/ . test ( 'Tom' )) console . log ( 'Hola Tom, Tam o Tim' ); si ( /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", "abbbbc" etc. if ( /ab{1,3}c/ . test ( "abc" )) console . log ( "OK" ); // coincidencia: "abc", "abbc", "abbbc"                  

Anclas

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

Subexpresión

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

Banderas

// /g - global // /i - ignora mayúsculas y minúsculas // /m - permite que las coincidencias abarquen varias líneasconsole.log ( "hola tom!" .replace(/Tom/i, "Juan")); // == "¡hola Juan!" console.log( " ratatam " .replace ( / ta / , " tu " ) ) ; // == " ratutam " console.log ( "ratatam".replace ( / ta / g , " tu " )); // == " ratutum"      

Métodos avanzados

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

Captura de 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 } en ${ 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 utilizando 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 de 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 heredar el del lugar donde se llamó o en 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 declaración de retorno) const addImplicit = ( x , y ) => x + y ;                 añadir ( 1 , 2 ); // => 3 addImplicit ( 1 , 2 ) // => 3    

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

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

La elevación le permite utilizar la función antes de que se "declare":

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 ) { devolver 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) {  devolver x - y; }" */

Operadores

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

// Concatenar 2 cadenas console.log('He' + ' llo ' ) ; // muestra Hola   // Suma dos números console.log ( 2 + 6 ); // muestra 8   // Agregar 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 en un número usando el suma unario console.log ( + '2' === 2 ) ; // muestra verdadero console.log ( + 'Hello' ); // muestra NaN    

De manera 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 ( ' hola' * 'mundo' ); // muestra NaN      

Aritmética

JavaScript admite los siguientes operadores aritméticos binarios :

JavaScript admite los siguientes operadores aritméticos unarios :

sea ​​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 después de la división por el módulo. Si se trata de 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 devolver siempre un número no negativo, vuelva a sumar el módulo y aplique el operador de módulo nuevamente:

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

También podrías hacer:

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

Asignación

Asignación de tipos primitivos

sea ​​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 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 hace con 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 2                          object_3 . a = 5 ; // object_3 no cambia object_2 message (); // muestra 7 7 5    objeto_3 = objeto_2 ; objeto_3 . a = 4 ; // objeto_3 cambia objeto_1 y objeto_2 mensaje (); // muestra 4 4 4    /** * Imprime el mensaje console.log */ 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 de 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 que deben recibir las subestructuras del valor asignado.

sea ​​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' , 'Contenido' ]}; const arr = []; ({ baz : [ arr [ 0 ], arr [ 3 ]], foo : a , bar : b } = e ); console.log ( ` $ { a } , ${ b } , ${ arr } ` ); // muestra : 5,6,Baz,,,Contenido [ 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 spread/rest

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

La sintaxis de propagación proporciona otra forma de desestructurar matrices y objetos. En el caso de las matrices, indica que los elementos se deben utilizar como parámetros en una llamada de función o como elementos en un literal de matriz. En el caso de los objetos, se puede utilizar para fusionar objetos o anular 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 }.

constante a = [ 1 , 2 , 3 , 4 ];      // Se puede utilizar varias veces en la misma expresión.constante b = [... a , ... a ]; // b = [1, 2, 3, 4, 1, 2, 3, 4];     //Se puede combinar con elementos no propagados.constante c = [ 5 , 6 , ... a , 7 , 9 ]; // c = [5, 6, 1, 2, 3, 4, 7, 9];        // A modo de comparación, hacer esto sin el operador de propagación// crea una matriz anidada.constante d = [ a , a ]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]     // Funciona igual con llamadas de función.función foo ( arg1 , arg2 , arg3 ) {     consola .log ( ` ${ arg1 } : ${ arg2 } : ${ arg3 } ` ) ;}// Puedes usarlo incluso si pasa más parámetros de los que utilizará la funciónfoo (... a ); // "1:2:3" → foo(a[0], a[1], a[2], a[3]); // Puedes mezclarlo con parámetros no propagadosfoo ( 5 , ... a , 6 ); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);   // A modo de comparación, hacer esto sin el operador de propagación// asigna la matriz a arg1 y nada a los demás parámetros.foo ( a ); // "1,2,3,4:indefinido:indefinido" constante barra = { a : 1 , b : 2 , c : 3 };          // Esto copiaría el objetoconst copia = { ... barra }; // copia = { a: 1, b: 2, c: 3 };      // "b" se anularía aquíconst anulación = { ... bar , b : 4 }; // anulación = { a: 1, c: 3, b: 4 }        

Cuando ...se utiliza en una declaración de función , indica un parámetro restante . El parámetro restante debe ser el último parámetro nombrado en la lista de parámetros de la función. Se le asignará un Arrayque contenga todos los argumentos pasados ​​a la función que excedan los otros parámetros nombrados. En otras palabras, obtiene "el resto" de los argumentos pasados ​​a la función (de ahí el 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 de descanso son similares al objeto de Javascript arguments, que es un objeto similar a una matriz que contiene todos los parámetros (con nombre y sin nombre) en la llamada de función actual. argumentsSin embargo, a diferencia de , los parámetros de descanso son objetos verdaderos , por lo que se pueden usar Arraymétodos como .slice()y directamente en 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 ); //falso console . log ( obj3 == obj1 ); //verdadero console . log ( obj3 === obj1 ); //verdadero                    

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 las siguientes :

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

// Sólo 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 verdadero console.log ( Boolean ( this ) === true ) ; console.log(Boolean ( { } ) === true ) ; console.log ( Boolean ( [ ]) === true );      // Estos tipos devuelven falso 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. Si se utiliza el operador dos veces seguidas, como doble negación , se convierte explícitamente una expresión en un primitivo de tipo booleano:

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

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

console.log ( [] == false ); console.log ( [] ? true : false ); // “veraz”, 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 ← verdadero console.log ([ 2 ] != verdadero ); console.log ([ 2 ] ? verdadero : falso ); // [2].toString() == "2" console.log ( " 2" ? = verdadero ); console.log ( "2" ? verdadero : falso ); // "2" → 2 ... (2?= 1) ... 1 verdadero                                                  

Las expresiones que utilizan funciones como post–incrementación ( ) tienen un efecto secundarioi++ anticipado . JavaScript proporciona una evaluación de cortocircuito de las 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 en su lugar:

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 que están más familiarizados con el comportamiento en C pueden encontrar esta característica sorprendente, pero permite una expresión más concisa de patrones como la coalescencia nula :

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

Asignación lógica

Bit a bit

JavaScript admite los siguientes operadores binarios bit a bit :

Ejemplos:

const x = 11 & 6 ; consola . 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:

sea ​​x = 7 ; consola . log ( x ); // 7 x <<= 3 ; consola . log ( x ); // 7->14->28->56   

Cadena

Ejemplos:

let str = "ab" + "cd"; // "abcd"str += "e"; // "abcde"const str2 = "2" + 2; // "22", not "4" or 4.

??

JavaScript's nearest operator is ??, the "nullish coalescing operator", which was added to the standard in ECMAScript's 11th edition.[14] In earlier versions, it could be used via a Babel plugin, and in TypeScript. It evaluates its left-hand operand and, if the result value is not "nullish" (null or undefined), takes that value as its result; otherwise, it evaluates the right-hand operand and takes the resulting value as its result.

In the following example, a will be assigned the value of b if the value of b is not null or undefined, otherwise it will be assigned 3.

const a = b ?? 3;

Before the nullish coalescing operator, programmers would use the logical OR operator (||). But where ?? looks specifically for null or undefined, the || operator looks for any falsy value: null, undefined, "", 0, NaN, and of course, false.

In the following example, a will be assigned the value of b if the value of b is truthy, otherwise it will be assigned 3.

const a = b || 3;

Control structures

Compound statements

A pair of curly brackets { } and an enclosed sequence of statements constitute a compound statement, which can be used wherever a statement can be used.

If ... else

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

Conditional (ternary) operator

The conditional operator creates an expression that evaluates as one of two expressions depending on a condition. This is similar to the if statement that selects one of two statements to execute depending on a condition. I.e., the conditional operator is to expressions what if is to statements.

const result = condition ? expression : alternative;

is the same as:

if (condition) { const result = expression;} else { const result = alternative;}

Unlike the if statement, the conditional operator cannot omit its "else-branch".

Switch statement

The syntax of the JavaScript switch statement is as follows:

 switch (expr) { case SOMEVALUE: // statements; break; case ANOTHERVALUE: // statements for when ANOTHERVALUE || ORNAOTHERONE // no break statement, falling through to the following case case ORANOTHERONE: // statements specific to ORANOTHERONE (i.e. !ANOTHERVALUE && ORANOTHER); break; //The buck stops here. case YETANOTHER: // statements; break; default: // statements; break; }

For loop

The syntax of the JavaScript for loop is as follows:

 for (initial; condition; loop statement) { /* statements will be executed every time the for{} loop cycles, while the condition is satisfied */ }

or

 for (initial; condition; loop statement(iteration)) // one statement

For ... in loop

The syntax of the JavaScript for ... in loop is as follows:

for (var property_name in some_object) { // statements using some_object[property_name];}

While loop

The syntax of the JavaScript while loop is as follows:

while (condition) { statement1; statement2; statement3; ...}

Do ... while loop

The syntax of the JavaScript do ... while loop is as follows:

do { statement1; statement2; statement3; ...} while (condition);

With

The with statement adds all of the given object's properties and methods into the following block's scope, letting them be referenced as if they were local variables.

with (document) { const a = getElementById('a'); const b = getElementById('b'); const c = getElementById('c');};

The semantics are similar to the with statement of Pascal.

Because the availability of with statements hinders program performance and is believed to reduce code clarity (since any given variable could actually be a property from an enclosing with), this statement is not allowed in strict mode.

Labels

JavaScript supports nested labels in most implementations. Loops or blocks can be labelled for the break statement, and loops for continue. Although goto is a reserved word,[15] goto is not implemented in JavaScript.

loop1: for (let a = 0; a < 10; ++a) { if (a === 4) break loop1; // Stops after the 4th attempt console.log('a = ' + a); loop2: for (let b = 0; b < 10; ++b) { if (b === 3) continue loop2; // Number 3 is skipped if (b === 6) continue loop1; // Continues the first loop, 'finished' is not shown console.log('b = ' + b); } //end of loop2 console.log('finished');} //end of loop1block1: { console.log('Hello'); // Displays 'Hello' break block1; console.log('World'); // Will never get here}goto block1; // Parse error.

Functions

A function is a block with a (possibly empty) parameter list that is normally given a name. A function may use local variables. If you exit the function without a return statement, the value undefined is returned.

function gcd(number1, number2) { if (isNaN(number1*number2)) throw TypeError("Non-Numeric arguments not allowed."); 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//In the absence of parentheses following the identifier 'gcd' on the RHS of the assignment below,//'gcd' returns a reference to the function itself without invoking it.let mygcd = gcd; // mygcd and gcd reference the same function.console.log(mygcd(60, 40)); // 20

Functions are first class objects and may be assigned to other variables.

The number of arguments given when calling a function may not necessarily correspond to the number of arguments in the function definition; a named argument in the definition that does not have a matching argument in the call will have the value undefined (that can be implicitly cast to false). Within the function, the arguments may also be accessed through the arguments object; this provides access to all arguments using indices (e.g. arguments[0], arguments[1], ... arguments[n]), including those beyond the number of named arguments. (While the arguments list has a .length property, it is not an instance of Array; it does not have methods such as .slice(), .sort(), etc.)

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

Primitive values (number, boolean, string) are passed by value. For objects, it is the reference to the object that is passed.

const obj1 = {a : 1};const obj2 = {b : 2};function foo(p) { p = obj2; // Ignores actual parameter p.b = arguments[1];}foo(obj1, 3); // Does not affect obj1 at all. 3 is additional parameterconsole.log(`${obj1.a} ${obj2.b}`); // writes 1 3

Functions can be declared inside other functions, and access the outer function's local variables. Furthermore, they implement full closures by remembering the outer function's local variables even after the outer function has exited.

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" (not "foo var") even though foo() has exited.console.log(t); // Top

Async/await

The await operator in JavaScript can only be used from inside an async function or at the top level of a module. If the parameter is a promise, execution of the async function will resume when the promise is resolved (unless the promise is rejected, in which case an error will be thrown that can be handled with normal JavaScript exception handling). If the parameter is not a promise, the parameter itself will be returned immediately.[16]

Many libraries provide promise objects that can also be used with await, as long as they match the specification for native JavaScript promises. However, promises from the jQuery library were not Promises/A+ compatible until jQuery 3.0.[17]

Here's an example (modified from this[18] article):

async function createNewDoc() { let response = await db.post({}); // post a new doc return db.get(response.id); // find by id}async function main() { try { let doc = await createNewDoc(); console.log(doc); } catch (err) { console.log(err); }}main();
Node.js version 8 includes a utility that enables using the standard library callback-based methods as promises.[19]

Objects

For convenience, types are normally subdivided into primitives and objects. Objects are entities that have an identity (they are only equal to themselves) and that map property names to values ("slots" in prototype-based programming terminology). Objects may be thought of as associative arrays or hashes, and are often implemented using these data structures. However, objects have additional features, such as a prototype chain, which ordinary associative arrays do not have.

JavaScript has several kinds of built-in objects, namely Array, Boolean, Date, Function, Math, Number, Object, RegExp and String. Other objects are "host objects", defined not by the language, but by the runtime environment. For example, in a browser, typical host objects belong to the DOM (window, form, links, etc.).

Creating objects

Objects can be created using a constructor or an object literal. The constructor can use either a built-in Object function or a custom function. It is a convention that constructor functions are given a name that starts with a capital letter:

// Constructorconst anObject = new Object();// Object literalconst objectA = {};const objectA2 = {}; // A != A2, {}s create new objects as copies.const objectB = {index1: 'value 1', index2: 'value 2'};// Custom constructor (see below)

Object literals and array literals allow one to easily create flexible data structures:

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

This is the basis for JSON, which is a simple notation that uses JavaScript-like syntax for data exchange.

Methods

A method is simply a function that has been assigned to a property name of an object. Unlike many object-oriented languages, there is no distinction between a function definition and a method definition in object-related JavaScript. Rather, the distinction occurs during function calling; a function can be called as a method.

When called as a method, the standard local variable this is just automatically set to the object instance to the left of the ".". (There are also call and apply methods that can set this explicitly—some packages such as jQuery do unusual things with this.)

In the example below, Foo is being used as a constructor. There is nothing special about a constructor - it is just a plain function that initialises an object. When used with the new keyword, as is the norm, this is set to a newly created blank object.

Note that in the example below, Foo is simply assigning values to slots, some of which are functions. Thus it can assign different functions to different instances. There is no prototyping in this example.

function px() { return this.prefix + "X"; }function 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 a-Y b-Zfoo1.m3 = px; // Assigns the function itself, not its evaluated result, i.e. not px()const baz = {"prefix": "c-"};baz.m4 = px; // No need for a constructor to make an object.console.log("m1/m3/m4 " + foo1.m1() + foo1.m3() + baz.m4());// m1/m3/m4 a-X a-X c-Xfoo1.m2(); // Throws an exception, because foo1.m2 doesn't exist.

Constructors

Constructor functions simply assign values to slots of a newly created object. The values may be data or other functions.

Example: Manipulating an object:

function MyObject(attributeA, attributeB) { this.attributeA = attributeA; this.attributeB = attributeB;}MyObject.staticC = "blue"; // On MyObject Function, not objectconsole.log(MyObject.staticC); // blueconst object = new MyObject('red', 1000);console.log(object.attributeA); // redconsole.log(object.attributeB); // 1000console.log(object.staticC); // undefinedobject.attributeC = new Date(); // add a new propertydelete object.attributeB; // remove a property of objectconsole.log(object.attributeB); // undefined

The constructor itself is referenced in the object's prototype's constructor slot. So,

function Foo() {}// Use of 'new' sets prototype slots (for example, // x = new Foo() would set x's prototype to Foo.prototype,// and Foo.prototype has a constructor slot pointing back to Foo).const x = new Foo();// The above is almost equivalent toconst y = {};y.constructor = Foo;y.constructor();// Exceptx.constructor == y.constructor; // truex instanceof Foo; // truey instanceof Foo; // false// y's prototype is Object.prototype, not// Foo.prototype, since it was initialised with// {} instead of new Foo.// Even though Foo is set to y's constructor slot,// this is ignored by instanceof - only y's prototype's// constructor slot is considered.

Functions are objects themselves, which can be used to produce an effect similar to "static properties" (using C++/Java terminology) as shown below. (The function object also has a special prototype property, as discussed in the "Inheritance" section below.)

Object deletion is rarely used as the scripting engine will garbage collect objects that are no longer being referenced.

Inheritance

JavaScript supports inheritance hierarchies through prototyping in the manner of Self.

In the following example, the Derived class inherits from the Base class. When d is created as Derived, the reference to the base instance of Base is copied to d.base.

Derive does not contain a value for aBaseFunction, so it is retrieved from aBaseFunction when aBaseFunction is accessed. This is made clear by changing the value of base.aBaseFunction, which is reflected in the value of d.aBaseFunction.

Some implementations allow the prototype to be accessed or set explicitly using the __proto__ slot as shown below.

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; // Must be before new Derived()Derived.prototype.constructor = Derived; // Required to make `instanceof` workconst d = new Derived(); // Copies Derived.prototype to d instance's hidden prototype slot.d instanceof Derived; // trued 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); // true in Mozilla-based implementations and false in many others.

The following shows clearly how references to prototypes are copied on instance creation, but that changes to a prototype can affect all instances that refer to it.

function m1() { return "One"; }function m2() { return "Two"; }function m3() { return "Three"; }function Base() {}Base.prototype.m = m2;const bar = new Base();console.log("bar.m " + bar.m()); // bar.m Twofunction Top() { this.m = m3; }const t = new Top();const foo = new Base();Base.prototype = t;// No effect on foo, the *reference* to t is copied.console.log("foo.m " + foo.m()); // foo.m Twoconst baz = new Base();console.log("baz.m " + baz.m()); // baz.m Threet.m = m1; // Does affect baz, and any other derived classes.console.log("baz.m1 " + baz.m()); // baz.m1 One

In practice many variations of these themes are used, and it can be both powerful and confusing.

Exception handling

JavaScript includes a try ... catch ... finally exception handling statement to handle run-time errors.

The try ... catch ... finally statement catches exceptions resulting from an error or a throw statement. Its syntax is as follows:

try { // Statements in which exceptions might be thrown} catch(errorValue) { // Statements that execute in the event of an exception} finally { // Statements that execute afterward either way}

Initially, the statements within the try block execute. If an exception is thrown, the script's control flow immediately transfers to the statements in the catch block, with the exception available as the error argument. Otherwise the catch block is skipped. The catch block can throw(errorValue), if it does not want to handle a specific error.

In any case the statements in the finally block are always executed. This can be used to free resources, although memory is automatically garbage collected.

Either the catch or the finally clause may be omitted. The catch argument is required.

The Mozilla implementation allows for multiple catch statements, as an extension to the ECMAScript standard. They follow a syntax similar to that used in Java:

try { statement; }catch (e if e == "InvalidNameException") { statement; }catch (e if e == "InvalidIdException") { statement; }catch (e if e == "InvalidEmailException") { statement; }catch (e) { statement; }

In a browser, the onerror event is more commonly used to trap exceptions.

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

Native functions and methods

(Not related to Web browsers.)

eval (expression)

Evaluates the first parameter as an expression, which can include assignment statements. Variables local to functions can be referenced by the expression. However, eval represents a major security risk, as it allows a bad actor to execute arbitrary code, so its use is discouraged.[20]

> (function foo() {... var x = 7;... console.log("val " + eval("x + 2"));... })();val 9undefined

See also

References

  1. ^ JavaScript 1.1 specification
  2. ^ "Chapter 1. Basic JavaScript". speakingjs.com. Retrieved 22 September 2020.
  3. ^ Flanagan, David (2006). JavaScript: The definitive Guide. p. 16. ISBN 978-0-596-10199-2. Omitting semicolons is not a good programming practice; you should get into the habit of inserting them.
  4. ^ "Storing the information you need — Variables - Learn web development | MDN". developer.mozilla.org. 9 May 2023. Retrieved 23 June 2023.
  5. ^ "Values, Variables, and Literals - MDC". Mozilla Developer Network. 16 September 2010. Archived from the original on 29 June 2011. Retrieved 1 February 2020.
  6. ^ "JavaScript Hoisting". W3Schools. In JavaScript, a variable can be declared after it has been used. In other words; a variable can be used before it has been declared.
  7. ^ "JavaScript Scoping and Hoisting", Ben Cherry, Adequately Good, 2010-02-08
  8. ^ ECMA-262 5e edition clarified this behavior with the Declarative Environment Record and Object Environment Record. With this formalism, the global object is the Object Environment Record of the global Lexical Environment (the global scope).
  9. ^ "Template literals". MDN Web Docs. Retrieved 4 November 2023.
  10. ^ "Comparison Operators - MDC Doc Center". Mozilla. 5 August 2010. Retrieved 5 March 2011.
  11. ^ "The Elements of JavaScript Style". Douglas Crockford. Retrieved 5 March 2011.
  12. ^ "Spread syntax (...) - JavaScript | MDN". developer.mozilla.org. 25 September 2023.
  13. ^ "rest parameters".
  14. ^ "ECMAScript 2020 Language Specification". Ecma International. June 2020.
  15. ^ ECMA-262, Edition 3, 7.5.3 Future Reserved Words
  16. ^ "await - JavaScript (MDN)". Retrieved 2 May 2017.
  17. ^ "jQuery Core 3.0 Upgrade Guide". Retrieved 2 May 2017.
  18. ^ "Taming the asynchronous beast with ES7". Retrieved 12 November 2015.
  19. ^ Foundation, Node.js (30 May 2017). "Node v8.0.0 (Current) - Node.js". Node.js.
  20. ^ "eval()". MDN Web Docs. Retrieved 29 January 2020.

Further reading

External links