La sintaxis de JavaScript es el conjunto de reglas que definen un programa JavaScript correctamente estructurado.
Los ejemplos siguientes 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 de salida de texto estándar oficial (con la excepción de document.write
). Dado que JavaScript se utiliza principalmente para secuencias de comandos del lado del cliente dentro de los navegadores web modernos , y que casi todos los navegadores web proporcionan la función de alerta, alert
también se puede utilizar, pero no se utiliza habitualmente.
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.
JavaScript distingue entre mayúsculas y minúsculas . Es común comenzar 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 ; consola . iniciar sesión ( un ); // 5 consola . iniciar sesión ( A ); // arroja un error de referencia: A no está definido
A diferencia de C , los espacios en blanco en el código JavaScript pueden afectar directamente la semántica . El punto y coma finaliza las declaraciones en JavaScript. Debido a la inserción automática de punto y coma (ASI), algunas declaraciones que están bien formadas cuando se analiza una nueva línea se considerarán completas, como si se insertara un punto y coma justo antes de la nueva línea. Algunas autoridades recomiendan proporcionar punto y coma al final de la declaración de forma explícita, porque puede disminuir los efectos no deseados de la inserción automática de punto y coma. [3]
Hay dos cuestiones: 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 determinadas posiciones, lo que podría provocar un análisis incorrecto.
Los cinco tokens problemáticos son el paréntesis abierto " (
", el corchete abierto " [
", la barra diagonal " /
", más " +
" y menos " -
". De estos, el paréntesis abierto es común en el patrón de expresión de función inmediatamente invocada , y el paréntesis abierto ocurre a veces, mientras que otros son bastante raros. Un ejemplo:
a = b + c ( d + mi ). foo () // Tratado 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 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 cuando se reorganiza. Por ejemplo:
a = b + c ;( d + mi ). foo () // Tratada como: // a = b + c; // (d + e).foo();
Los puntos y coma iniciales también se utilizan a veces al inicio de las bibliotecas de JavaScript, en caso de que se agreguen a otra biblioteca que omita un punto y coma al final, ya que esto puede resultar en 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. return
y throw
toma un valor opcional, mientras que break
y continue
toma una etiqueta opcional. En todos los casos, el consejo es mantener el valor o etiqueta en la misma línea que la declaración. Esto suele aparecer en la declaración de devolución, donde se puede devolver un objeto literal grande, que podría colocarse accidentalmente comenzando en una nueva línea. Para el post-incremento/decremento, existe una posible ambigüedad con el pre-incremento/decremento, y nuevamente se recomienda simplemente mantenerlos en la misma línea.
devolver a + b ; // Devuelve indefinido. Tratado como: // retorno; // a + b; // Debe escribirse como: // return a + b;
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 script. Que algún día sea grandioso. *//* Comentarios /* puede que no estén anidados */ Error de sintaxis * /
Las variables en JavaScript estándar no tienen ningún 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 pueden declarar var
para variables de ámbito de función o let
para const
variables de nivel de bloque . Antes de ES6, las variables solo podían declararse mediante una var
declaración. Los valores asignados a las variables declaradas con const
no se pueden cambiar, pero sus propiedades sí. var
Ya no deberían utilizarse desde entonces let
y const
son 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úscula "A" a "Z" son diferentes de los caracteres en minúscula "a" a "z".
A partir de JavaScript 1.5, se pueden utilizar ISO 8859-1 o letras Unicode (o secuencias de escape Unicode) en los identificadores. [5] En ciertas implementaciones de JavaScript, el signo de arroba (@) se puede usar en un identificador, pero esto es contrario a las especificaciones y no se admite en implementaciones más nuevas. [ cita necesaria ]\uXXXX
Las variables declaradas con var
tienen un alcance léxico a nivel de función , mientras que las que tienen let
o const
tienen un alcance a nivel de bloque . Dado que las declaraciones se procesan antes de ejecutar cualquier código, se puede asignar y utilizar una variable antes de declararla en el código. [6] Esto se conoce comohoisting , y es equivalente a que las variables sedeclaren hacia adelanteen la parte superior de la función o bloque.[7]
Con declaraciones var
, let
y const
, solo se eleva la declaración; Las asignaciones no se elevan. Por lo tanto, una declaración en el medio de la función es equivalente a una declaración en la parte superior de la función y una declaració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 declararlos; La referencia directa 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 = 1
var x
x = 1
var
undefined
let
const
Las declaraciones de funciones, que declaran una variable y le asignan una función, son similares a las declaraciones de variables, pero además de elevar la declaración, también elevan la asignación, como si toda la declaración apareciera en la parte superior de la función que la contiene, y por lo tanto La referencia directa también es posible: la ubicación de una declaración de función dentro de una función adjunta es irrelevante. Esto es diferente de una expresión de función asignada a una variable en una declaración var
, let
o .const
Así, por ejemplo,
var func = function () { .. } // la declaración se eleva solo function func () { .. } // la declaración y la asignación se elevan
El alcance del 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 let
palabra clave.
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, busca en el ámbito local. Si no se encuentra este identificador, busca en el siguiente ámbito externo y así sucesivamente a lo largo de la cadena de ámbito hasta llegar al ámbito global donde residen las variables globales. Si aún no se encuentra, JavaScript generará una ReferenceError
excepción.
Al asignar un identificador, JavaScript pasa exactamente por el mismo proceso para recuperar este identificador, excepto que si no se encuentra en el alcance global , creará la "variable" en el alcance donde fue creado. [8] Como consecuencia, una variable nunca declarada será global, si se asigna. Declarar una variable (con la palabra clave var
) en el alcance 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 ventana ) También cree 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 global del espacio de nombres.
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 function f () { var z = 'zorros' , r = 'pájaros' ; // 2 variables locales m = 'pez' ; // global, porque no fue declarado en ningún lugar antes función hijo () { var r = 'monos' ; // Esta variable es local y no afecta a los "pájaros" r de la función principal. z = 'pingüinos' ; // Cierre: la función secundaria puede acceder a las variables de la función principal. } veinte = 20 ; // Esta variable se declara en la línea siguiente, 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 ();consola . iniciar sesión ( z ); // Esta línea generará una excepción ReferenceError, porque el valor de z ya no está disponible
para ( sea i = 0 ; i < 10 ; i ++ ) consola . iniciar sesión ( yo ); consola . iniciar sesión ( yo ); // arroja un error de referencia: no estoy definido
para ( const i = 0 ; i < 10 ; i ++ ) consola . iniciar sesión ( yo ); // arroja un TypeError: Asignación a variable constante para ( const i de [ 1 , 2 , 3 ]) consola . iniciar sesión ( yo ); //no generará una excepción. No soy reasignado sino recreado en cada iteración. pi constante ; // arroja un error de sintaxis: falta el inicializador en la declaración constante
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 nombrados se describen en las secciones correspondientes a continuación.
El valor "indefinido" 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 indefinido se considera un valor falso.
Nota: indefinido se considera un tipo primitivo genuino. A menos que se convierta explícitamente, el valor indefinido puede comportarse inesperadamente en comparación con otros tipos que se evalúan como falso en un contexto lógico.
dejar probar ; // variable declarada, pero no definida, ... // ... establecida en el valor de const testObj = {}; consola . iniciar sesión ( prueba ); // la variable de prueba existe, pero el valor no... // ... definido, muestra una consola no definida . iniciar sesión ( testObj . myProp ); // testObj existe, la propiedad no, ... // ... muestra una consola indefinida . iniciar sesión ( indefinido == nulo ); // tipo no aplicado durante la verificación, muestra la consola verdadera . iniciar sesión ( indefinido === nulo ); // aplicar el tipo durante la verificación, muestra falso
Nota: No existe un lenguaje literal incorporado para indefinido. Por lo tanto, no es una forma infalible de comprobar si una variable no está definida, 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 esta no funcionarán como se esperaba:
la función es indefinida ( x ) { let u ; devolver x === u ; } // así... la función no está definida ( x ) { return x === void 0 ; } // ... o esa segunda función es Undefinida ( x ) { return ( typeof x ) === "indefinido" ; } // ... o ese tercero
Aquí, llamar isUndefined(my_var)
genera un ReferenceError si my_var es un identificador desconocido, mientras que no.typeof my_var === 'undefined'
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 exactamente números reales, incluidas las fracciones.
Esto se convierte en un problema al comparar o formatear números. Por ejemplo:
consola . Iniciar sesión ( 0,2 + 0,1 === 0,3 ); // muestra una consola falsa . iniciar sesión ( 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 formatee para su salida.
Los números pueden especificarse en cualquiera de estas notaciones:
345 ; // un "entero", aunque sólo hay un tipo numérico en JavaScript 34.5 ; // un número de punto flotante 3.45e2 ; // otro 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, los 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 ; // Usado con números grandes 1 _000_000 .5 ; // Soporte con decimales 1 _000e1_000 ; // Soporte con exponentes // Soporte con binario, octal y hexadecimal 0b0000 _0000_0101_1011 ; 0o0001 _3520_0237_1327 ; 0xFFFF_FFFF_FFFF_FFFE ;// Pero no puedes usarlos junto a una parte numérica 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 separador que no es un dígito. Solo se permite 1 separador a la vez
Las extensiones +∞ , −∞ y NaN (No es un número) del tipo numérico se pueden obtener mediante dos expresiones de programa:
Infinidad ; // infinito positivo (negativo obtenido con -Infinity por ejemplo) NaN ; // El valor Not-A-Number, también devuelto como error en ... // ... conversiones de cadena a número
Infinity y NaN son números:
tipo de infinito ; // devuelve "número" tipo de NaN ; // devuelve "número"
Estos tres valores especiales se corresponden y se comportan como los describe IEEE-754 .
El constructor Número (usado como función), o un + o - unario, se puede usar para realizar una conversión numérica explícita:
const miCadena = "123.456" ; const miNúmero1 = Número ( miCadena ); const miNúmero2 = + 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 // Puedes utilizar los métodos isNaN para comprobar la consola NaN . log ( isNaN ( "convertido a NaN" )); // verdadera consola . iniciar sesión ( isNaN ( NaN )); // verdadera consola . log ( Número . isNaN ( "no convertido" )); // consola falsa . log ( Número . isNaN ( NaN )); // verdadero
BigInts se puede 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 la primitiva Número y representado por la constante Number.MAX_SAFE_INTEGER.
Al dividir BigInts, los resultados se truncan .
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 con escape (como \ n). El estándar JavaScript permite que el carácter de comillas invertidas (`, también conocido como acento grave o comillas invertidas) cite cadenas literales de varias líneas, así como literales de plantilla, que permiten la interpolación de expresiones evaluadas con tipo forzado dentro de una cadena [9] .
const saludo = "¡Hola mundo!" ; const anotherGreeting = 'Saludos, gente de la Tierra.' ; const aMultilineGreeting = `Saludos cordiales, John Doe.` // Los literales de plantilla fuerzan el tipo de expresiones evaluadas y las interpolan en la cadena. const templateLiteral = `Esto es lo que está almacenado en anotherGreeting: ${ anotherGreeting } .` ; consola . iniciar sesión ( plantillaLiteral ); // 'Esto es lo que está almacenado en otroSaludo: 'Saludos, gente de la Tierra.''
Se puede acceder a los caracteres individuales dentro de una cadena mediante el método charAt (proporcionado por String.prototype ). Esta es la forma preferida al acceder a caracteres individuales dentro de una cadena, porque también funciona en navegadores no modernos:
const h = saludo . 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 las matrices:
const h = saludo [ 0 ];
Sin embargo, las cadenas de JavaScript son inmutables :
saludo [ 0 ] = "H" ; // Falla.
Aplicar el operador de igualdad ("==") a dos cadenas devuelve verdadero, si las cadenas tienen el mismo contenido, lo que significa: de la misma longitud y que contienen la misma secuencia de caracteres (las mayúsculas y minúsculas son significativas para los alfabetos). De este modo:
const x = "Mundo" ; const compare1 = ( "Hola", + x == "Hola, mundo" ); // Aquí compare1 contiene verdadero. const compare2 = ( "Hola", + x == "hola, mundo" ); // Aquí compare2 contiene ... // ... false ya que los ... // ... primeros caracteres ... // ... de ambos operandos ... // ... no son iguales caso.
Las citas del mismo tipo no se pueden anidar a menos que tengan escape .
let x = '"¡Hola mundo!" dijo.' ; // Muy bien. x = "" ¡ Hola mundo ! " dijo." ; // No es bueno. x = "\"¡Hola mundo!\", dijo." ; // Funciona escapando " con \"
El constructor String crea un objeto de cadena (un objeto que envuelve una cadena):
const saludo = nueva cadena ( "¡Hola, mundo!" );
Estos objetos tienen un método valueOf que devuelve la cadena primitiva envuelta dentro de ellos:
const s = nueva cadena ( "¡Hola!" ); tipo de s ; // Es 'objeto'. tipo de s . valor de (); // Es 'cadena'.
La igualdad entre dos objetos String no se comporta como con las primitivas de cadena:
const s1 = nueva cadena ( "¡Hola!" ); const s2 = nueva cadena ( "¡Hola!" ); s1 == s2 ; // Es falso, porque son dos objetos distintos. s1 . valor de () == s2 . valor de (); // Es cierto.
JavaScript proporciona un tipo de datos booleano con literales verdaderos y falsos . El operador typeof devuelve la cadena "booleana" para estos tipos primitivos . Cuando se usa en un contexto lógico, 0 , -0 , nulo , NaN , undefinido y la cadena vacía ( "" ) se evalúan como falso 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" , "falso" y cualquier objeto.
La coerción de tipo automática por parte de los operadores de comparación de igualdad ( ==
y !=
) se puede evitar utilizando los operadores de comparación de tipo verificado ( ===
y !==
).
Cuando se requiere conversión de tipos, JavaScript convierte operandos booleanos , numéricos , de cadena u objetos de la siguiente manera: [10]
Douglas Crockford defiende los términos " verdadero " y " falso " para describir cómo se comportan valores de diversos tipos cuando se evalúan en un contexto lógico, especialmente en lo que respecta a 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. Se devuelve el operando izquierdo, si puede evaluarse como: falso , en el caso de conjunción : ( ), o verdadero , en el caso de 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 en casos de operandos booleanos mixtos y compatibles con números (incluidas cadenas que pueden evaluarse como un número u objetos que pueden evaluarse como tal cadena), porque el operando booleano se comparará como un valor numérico. Esto puede resultar 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 booleana() o usando el operador condicional : ( ).a && b
a || b
c ? t : f
// Consola de coerción de tipo automático . iniciar sesión ( verdadero == 2 ); // falso... verdadero → 1 !== 2 ← 2 consola . iniciar sesión ( falso == 2 ); // falso... falso → 0 !== 2 ← 2 consola . iniciar sesión ( verdadero == 1 ); // verdadero.... verdadero → 1 === 1 ← 1 consola . iniciar sesión ( falso == 0 ); // verdadero.... falso → 0 === 0 ← 0 consola . iniciar sesión ( verdadero == "2" ); // falso... verdadero → 1 !== 2 ← "2" consola . iniciar sesión ( falso == "2" ); // falso... falso → 0 !== 2 ← "2" consola . iniciar sesión ( verdadero == "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 !== NaN consola . iniciar sesión ( NaN == NaN ); // false...... NaN no es equivalente a nada, incluido NaN. // Consola de comparación de tipos verificados (sin conversión de tipos y valores) . iniciar sesión ( verdadero === 1 ); // falso...... los tipos de datos no coinciden // Consola de coerción de tipo explícito . iniciar sesión ( verdadero === !! 2 ); // verdadero.... los tipos de datos y los valores coinciden con la consola . iniciar sesión ( verdadero === !! 0 ); // falso... los tipos de datos coinciden, pero los valores difieren consola . iniciar sesión ( 1 ? verdadero : falso ); // verdadero.... sólo ±0 y NaN son números "falsos" console . iniciar sesión ( "0" ? Verdadero : falso ); // verdadero.... sólo la cadena vacía es consola "falsa" . iniciar sesión ( booleano ({})); // verdadero.... todos los objetos son "veraces"
El nuevo operador se puede utilizar para crear un contenedor de objetos para una primitiva booleana. Sin embargo, el operador typeof no devuelve un valor booleano para el contenedor de objetos, sino que devuelve un objeto . Debido a que todos los objetos se evalúan como verdaderos , se debe utilizar un método como .valueOf() o .toString() para recuperar el valor ajustado. Para la coerción explícita al tipo booleano, Mozilla recomienda que se utilice la función booleana() (sin new ) con preferencia al objeto booleano.
const b = nuevo booleano ( falso ); // Objeto falso {} const t = booleano ( b ); // booleano verdadero const f = booleano ( b . valueOf ()); // booleano falso let n = nuevo booleano ( b ); // No recomendado n = new booleano ( b . valueOf ()); // Preferido if ( 0 || - 0 || "" || null || indefinido || b . valueOf () || ! new booleano () || ! t ) { console . log ( "Nunca esto" ); } else if ([] && {} && b && typeof b === "objeto" && b . toString () === "falso" ) { console . log ( "Siempre esto" ); }
Nuevo 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 objeto de símbolo constante = {}; const objeto normal = {}; // dado que x e y son únicos, // pueden usarse como claves únicas en un objeto symbolObject [ x ] = 1 ; símboloObjeto [ y ] = 2 ; símboloObjeto [ x ]; // => 1 objeto símbolo [ y ]; // => 2 // en comparación con las claves numéricas normales normalObject [ 1 ] = 1 ; objeto normal [ 1 ] = 2 ; // anula el valor de 1 objeto normal [ 1 ]; // => 2 // cambiar el valor de x no cambia la clave almacenada en el objeto x = Símbolo ( 3 ); símboloObjeto [ x ]; // => indefinido // volver a cambiar x simplemente crea otro símbolo único x = Símbolo ( 1 ); símboloObjeto [ x ]; // => indefinido
También hay símbolos muy conocidos .
Uno de los cuales es Symbol.iterator
; si algo se implementa Symbol.iterator
, es iterable:
constante x = [ 1 , 2 , 3 , 4 ]; // x es una matriz x [ Símbolo . iterador ] === Matriz . prototipo [ Símbolo . iterador ]; // y las matrices son iterables const xIterador = x [ Símbolo . iterador ](); // La función [Symbol.iterator] debe proporcionar un iterador para x xIterator . próximo (); // { valor: 1, hecho: falso } xIterator . próximo (); // { valor: 2, hecho: falso } xIterator . próximo (); // { valor: 3, hecho: falso } xIterator . próximo (); // { valor: 4, hecho: falso } xIterator . próximo (); // { valor: indefinido, hecho: verdadero } xIterator . próximo (); // { valor: indefinido, hecho: verdadero } // los bucles for..of iteran automáticamente los valores for ( valor constante de x ) { console . iniciar sesión ( valor ); // 1 2 3 4 } // Los conjuntos también son iterables: [ Símbolo . iterador ] en Set . prototipo ; // verdadero for ( valor constante del nuevo conjunto ([ 'manzana' , 'naranja' ])) { consola . iniciar sesión ( valor ); // "manzana" "naranja" }
El lenguaje JavaScript proporciona un puñado de objetos nativos . Los objetos nativos de JavaScript se consideran parte de la especificación de JavaScript. Independientemente del entorno JavaScript, este conjunto de objetos siempre debería estar disponible.
Una matriz es un objeto JavaScript creado a partir del Array
constructor diseñado específicamente para almacenar valores de datos indexados por claves enteras. Las matrices, a diferencia del tipo de objeto básico, tienen prototipos 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 , las matrices utilizan un esquema de indexación de base cero: un valor que se inserta en una matriz vacía mediante el push
método ocupa el índice 0 de la matriz.
const miArray = []; // Apunta la variable myArray a un Array myArray recién creado y vacío . empujar ( "hola mundo" ); // Complete el siguiente índice vacío, en este caso 0 console . iniciar sesión ( miArray [ 0 ]); // Equivalente a console.log("hola mundo");
Las matrices tienen una length
propiedad que se 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. Escribir un número menor en la length
propiedad eliminará índices más grandes.
Array
Se puede acceder a los elementos de s utilizando la notación normal de acceso a propiedades de objetos:
miArray [ 1 ]; // el segundo elemento en myArray myArray [ "1" ];
Los dos anteriores son equivalentes. No es posible utilizar la notación de "punto" o cadenas con representaciones alternativas del número:
miArray .1 ; // error de sintaxis myArray [ "01" ]; // no es lo mismo que myArray[1]
La declaración de una matriz puede utilizar un Array
literal o el Array
constructor:
dejar 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 completar 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 sólo los elementos definidos utilicen memoria; son " matrices dispersas ". Configuración y sólo utiliza espacio para estos dos elementos, como cualquier otro objeto. El valor de la matriz aún se informará como 58. La longitud máxima de una matriz es 4,294,967,295, que corresponde a un número binario de 32 bits (11111111111111111111111111111111) 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 forma muy parecida a matrices asociativas en otros lenguajes:
const perro = { color : "marrón" , tamaño : "grande" }; perro [ "color" ]; // da como resultado un perro "marrón" . color ; // también resulta en "marrón"
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 : "marrón" , tamaño : "grande" }, mancha : { color : "negro" , tamaño : "pequeño" }}; perros [ "mancha" ][ "tamaño" ]; // da como resultado perros "pequeños" . vehículo explorador . color ; // da como resultado "marrón"
Un Date
objeto almacena un recuento de milisegundos con signo, donde el cero representa 1970-01-01 00:00:00 UT y un rango de ±10 8 días. Hay varias formas de proporcionar argumentos al Date
constructor. Tenga en cuenta que los meses son de base cero.
nueva fecha (); // crea una nueva instancia de Fecha que representa la hora/fecha actual. nueva fecha ( 2010 , 2 , 1 ); // crea una nueva instancia de Fecha que representa 2010-Mar-01 00:00:00 nueva Fecha ( 2010 , 2 , 1 , 14 , 25 , 30 ); // crea una nueva instancia de Fecha que representa 2010-3-1 14:25:30 nueva Fecha ( "2010-3-1 14:25:30" ); // crea una nueva instancia de Fecha a partir de una Cadena.
Se proporcionan métodos para extraer campos, así como una útil toString
:
const d = nueva fecha ( 2010 , 2 , 1 , 14 , 25 , 30 ); // 01 de marzo de 2010 14:25:30; // Muestra '2010-3-1 14:25:30': consola . log ( d . getFullYear () + '-' + ( d . getMonth () + 1 ) + '-' + d . getDate () + ' ' + d . getHours () + ':' + d . getMinutes () + ':' + d . obtenerSegundos ()); // El toString integrado devuelve algo como 'lunes 01 de marzo de 2010 14:25:30 GMT-0500 (EST)': consola . iniciar sesión ( d );
Se pueden crear mensajes de error personalizados usando la Error
clase:
lanzar un nuevo error ( "Algo salió mal." );
Estos pueden detectarse mediante bloques try...catch...finally como se describe en la sección sobre manejo de excepciones.
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 .
/expresión/ . prueba ( cadena ); // devuelve una "cadena" booleana . buscar ( /expresión/ ); // devuelve el número de posición "cadena" . reemplazar ( /expresión/ , reemplazo ); // Aquí hay algunos ejemplos if ( /Tom/ . test ( "Mi nombre es Tom" )) consola . iniciar sesión ( "¡Hola Tom!" ); consola . log ( "Mi nombre es Tom" . buscar ( /Tom/ )); // == 11 (letras antes de Tom) consola . log ( "Mi nombre es Tom" . reemplazar ( /Tom/ , "John" )); // == "Mi nombre es Juan"
// \d - dígito // \D - sin dígitos // \s - espacio // \S - sin espacio // \ w - palabra char // \W - sin palabra // [ ] - uno de // [ ^] - uno que no pertenece a // - - rangoif ( /\d/ . prueba ( '0' )) consola . iniciar sesión ( 'Dígito' ); if ( /[0-9]/ . prueba ( '6' )) consola . iniciar sesión ( 'Dígito' ); if ( /[13579]/ . prueba ( '1' )) consola . iniciar sesión ( 'Número impar' ); if ( /\S\S\s\S\S\S\S/ . prueba ( 'Mi nombre' )) consola . iniciar sesión ( 'Formatear Aceptar' ); if ( /\w\w\w/ . prueba ( 'Tom' )) consola . iniciar sesión ( 'Hola Tom' ); if ( /[a-zA-Z]/ . prueba ( 'B' )) consola . iniciar sesión ( 'Carta' );
// A...Z a...z 0...9 - alfanumérico // \u0000...\uFFFF - Unicode hexadecimal // \x00...\xFF - ASCII hexadecimal // \t - tabulador / / \n - nueva línea // \r - CR // . - cualquier carácter // | - Oif ( /Tm/ . prueba ( 'Tom' )) consola . log ( 'Hola Tom, Tam o Tim' ); if ( /A|B/ . prueba ( "A" )) consola . iniciar sesión ( 'A o B' );
// ? - 0 o 1 coincidencia // * - 0 o más // + - 1 o más // {n} - exactamente n // {n,} - no más // {0,n} - no menos // {n,m} - rango n a mif ( /ab?c/ . prueba ( "ac" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "ac", "abc" if ( /ab*c/ . prueba ( "ac" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "ac", "abc", "abbc", "abbbc", etc. if ( /ab+c/ . test ( "abc" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "abc", "abbc", "abbbc", etc. if ( /ab{3}c/ . test ( "abbbc" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "abbbc" if ( /ab{3,}c/ . prueba ( "abbbc" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "abbbc", "abbbbc", "abbbbbc", etc. if ( /ab{1,3}c/ . test ( "abc" )) consola . iniciar sesión ( "Aceptar" ); // coincidencia: "abc", "abbc", "abbbc"
// ^ - la cadena comienza con // $ - la cadena termina conif ( /^My/ . test ( "Mi nombre es Tom" )) consola . iniciar sesión ( "¡Hola!" ); if ( /Tom$/ . test ( "Mi nombre es Tom" )) consola . iniciar sesión ( "¡Hola Tom!" );
// ( ) - grupos de caracteresif ( /water(mark)?/ . test ( "watermark" )) consola . log ( "¡Aquí hay agua!" ); // coincidencia: "agua", "marca de agua", if ( /(Tom)|(John)/ . prueba ( "John" )) consola . log ( "¡Hola Tom o John!" );
// /g - global // /i - ignora mayúsculas/minúsculas // /m - permite que las coincidencias abarquen varias líneasconsola . log ( "¡hola tom!" . reemplazar ( /Tom/i , "John" )); // == "¡Hola Juan!" consola . log ( "ratatam" . reemplazar ( /ta/ , "tu" )); // == consola "ratutam" . log ( "ratatam" . reemplazar ( /ta/g , "tu" )); // == "ratutum"
mi_matriz = mi_cadena . dividir ( mi_delimitador ); // ejemplo my_array = "perro,gato,vaca" . dividir ( "," ); // my_array==["perro","gato","vaca"]; mi_matriz = mi_cadena . coincidencia ( mi_expresión ); // ejemplo my_array = "Empezamos a las 11:30, 12:15 y 16:45" . partido ( /\d\d:\d\d/g ); // mi_array==["11:30","12:15","16:45"];
const miRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/ ; resultados constantes = myRe . exec ( "La fecha y hora son 2009-09-08 09:37:08." ); si ( resultados ) { consola . log ( "Coincidente: " + resultados [ 0 ]); // Coincidencia completa const my_date = resultados [ 1 ]; // Primer grupo == "2009-09-08" const my_time = resultados [ 2 ]; // Segundo grupo == consola "09:37:08" . log ( `Es ${ my_time } el ${ my_date } ` ); } más consola . log ( "¡No encontré una fecha válida!" );
Cada función en JavaScript es una instancia del Function
constructor:
// 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 = nueva función ( 'x' , 'y' , 'return x + y' ); agregar ( 1 , 2 ); // => 3
La función agregar anterior también se puede definir usando una expresión de función:
const agregar = función ( x , y ) { retorno x + y ; }; agregar ( 1 , 2 ); // => 3
En ES6, se agregó la sintaxis de la función de flecha, lo que permite que las funciones que devuelven un valor sean más concisas. También conservan la propiedad this
del objeto global en lugar de heredarla desde dónde se llamó/cómo se llamó, a diferencia de la function() {}
expresión.
const agregar = ( x , y ) => { return x + y ;}; // los valores también se pueden devolver implícitamente (es decir, no se necesita una declaración de devolución) const addImplicit = ( x , y ) => x + y ; agregar ( 1 , 2 ); // => 3 agregarImplicit ( 1 , 2 ) // => 3
Para funciones que necesitan ser elevadas, existe una expresión separada:
función agregar ( x , y ) { retorno x + y ; } agregar ( 1 , 2 ); // => 3
El levantamiento le permite utilizar la función antes de que sea "declarada":
agregar ( 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 ; } consola . log ( restar . longitud ); // => 2, aridad de la función (número de argumentos) consola . log ( restar . toString ()); /* "función restar(x, y) { return x - y; }" */
El operador '+' está sobrecargado : se utiliza para la concatenación de cadenas y la suma aritmética. Esto puede causar problemas al mezclar cadenas y números sin darse cuenta. Como operador unario, puede convertir una cadena numérica en un número.
// Concatenar 2 cadenas consola . iniciar sesión ( 'Él' + 'llo' ); // muestra Hola // Agrega dos números a la consola . Iniciar sesión ( 2 + 6 ); // muestra 8 // Agregar un número y una cadena da como resultado la concatenación (de izquierda a derecha) console . iniciar sesión ( 2 + '2' ); // muestra 22 consolas . iniciar sesión ( '$' + 3 + 4 ); // muestra $34, pero es posible que se esperaran $7 por consola . iniciar sesión ( '$' + ( 3 + 4 )); // muestra la consola $7 . iniciar sesión ( 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 la consola unaria plus . iniciar sesión ( + '2' === 2 ); // muestra la consola verdadera . iniciar sesión ( + 'Hola' ); // muestra NaN
De manera similar, el operador '*' está sobrecargado: puede convertir una cadena en un número.
consola . iniciar sesión ( 2 + '6' * 1 ); // muestra 8 consolas . iniciar sesión ( 3 * '7' ); // 21 consola . iniciar sesión ( '3' * '7' ); // 21 consola . iniciar sesión ( 'hola' * 'mundo' ); // muestra NaN
JavaScript admite los siguientes operadores aritméticos binarios :
JavaScript admite los siguientes operadores aritméticos unarios :
sea x = 1 ; consola . iniciar sesión ( ++ x ); // x se convierte en 2; Muestra 2 consolas . iniciar sesión ( x ++ ); // muestra 2; x se convierte en 3 consolas . iniciar sesión ( x ); // x es 3; Muestra 3 consolas . iniciar sesión ( x- ) ; // muestra 3; x se convierte en 2 consolas . iniciar sesión ( x ); // muestra 2; x son 2 consolas . iniciar sesión ( -x ) ; // x se convierte en 1; muestra 1
El operador de 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.
constante x = 17 ; consola . Iniciar sesión ( x % 5 ); // muestra 2 consolas . Iniciar sesión ( x % 6 ); // muestra 5 consolas . Iniciar sesión ( -x % 5 ) ; // muestra -2 consola . iniciar sesión ( -x % -5 ) ; // muestra -2 consola . iniciar sesión ( x %-5 ) ; // muestra 2
Para devolver siempre un número no negativo, vuelva a agregar el módulo y aplique el operador de módulo nuevamente:
constante x = 17 ; consola . Iniciar sesión (( -x % 5 + 5 ) % 5 ) ; // muestra 3
También puedes hacer:
constante x = 17 ; consola . log ( Matemáticas . abs ( - x % 5 )); // también 3
Asignación de tipos primitivos.
sea x = 9 ; x += 1 ; consola . iniciar sesión ( x ); // muestra: 10 x *= 30 ; consola . iniciar sesión ( x ); // muestra: 300 x /= 6 ; consola . iniciar sesión ( x ); // muestra: 50 x -= 3 ; consola . iniciar sesión ( x ); // muestra: 47 x %= 7 ; consola . iniciar sesión ( 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 }; dejar objeto_3 = objeto_2 ; // objeto_3 hace referencia al mismo objeto que objeto_2 hace referencia a objeto_3 . a = 2 ; mensaje (); // muestra 1 2 2 objeto_2 = objeto_1 ; // objeto_2 ahora hace referencia al mismo objeto que objeto_1 // objeto_3 todavía hace referencia a lo que objeto_2 hacía referencia antes del mensaje (); // muestra 1 1 2 objeto_2 . a = 7 ; // modifica el mensaje object_1 (); // muestra 7 7 2 objeto_3 . a = 5 ; // objeto_3 no cambia el mensaje objeto_2 (); // muestra 7 7 5 objeto_3 = objeto_2 ; objeto_3 . a = 4 ; // objeto_3 cambia el mensaje objeto_1 y objeto_2 (); // muestra 4 4 4 /** * Imprime el mensaje console.log */ function message () { console . log ( objeto_1 . a + " " + objeto_2 . a + " " + objeto_3 . a ); }
En JavaScript de Mozilla, desde la versión 1.7, la asignación desestructurante permite la asignación de 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 objeto/matriz literal anidado arbitrariamente que contiene valores l-l en sus hojas que van a recibir las subestructuras del valor asignado.
sean a , b , c , d , e ; [ a , b , c ] = [ 3 , 4 , 5 ]; consola . iniciar sesión ( ` ${ a } , ${ b } , ${ c } ` ); // muestra: 3,4,5 e = { foo : 5 , bar : 6 , baz : [ 'Baz' , 'Contenido' ]}; configuración constante = [ ]; ({ baz : [ arr [ 0 ], arr [ 3 ]], foo : a , bar : b } = e ); consola . iniciar sesión ( ` ${ a } , ${ b } , ${ arr } ` ); // muestra: 5,6,Baz,,,Contenido [ a , b ] = [ b , a ]; // intercambia el contenido de las consolas a y b . iniciar sesión ( a + ',' + b ); // muestra: 6,5 [ a , b , c ] = [ 3 , 4 , 5 ]; // permutaciones [ a , b , c ] = [ b , c , a ]; consola . iniciar sesión ( ` ${ a } , ${ b } , ${ c } ` ); // muestra: 4,5,3
El estándar ECMAScript 2015 introdujo el ...
operador de matriz " ", para los conceptos relacionados de "sintaxis extendida" [12] y "parámetros restantes". [13] La distribución de objetos se agregó en ECMAScript 2018.
La sintaxis extendida proporciona otra forma de desestructurar matrices y objetos. Para las matrices, indica que los elementos deben usarse como parámetros en una llamada de función o como elementos en un literal de matriz. Para 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 usar varias veces en la misma expresiónconstante b = [... a , ... a ]; // b = [1, 2, 3, 4, 1, 2, 3, 4]; // Se puede combinar con artículos no extendidos.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 extensión// crea una matriz anidada.constante d = [ a , a ]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]] // Funciona igual con llamadas a funcionesfunción foo ( arg1 , arg2 , arg3 ) { consola . iniciar sesión ( ` ${ arg1 } : ${ arg2 } : ${ arg3 } ` );}// Puedes usarlo incluso si pasa más parámetros de los que usará la funciónfoo (... un ); // "1:2:3" → foo(a[0], a[1], a[2], a[3]); // Puedes mezclarlo con parámetros no extendidosfoo ( 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 extensión// asigna la matriz a arg1 y nada a los demás parámetros.foo ( un ); // "1,2,3,4:indefinido:indefinido" barra constante = { a : 1 , b : 2 , c : 3 }; // Esto copiaría el objetocopia constante = { ... barra }; // copiar = { a: 1, b: 2, c: 3 }; // "b" se anularía aquíanulación constante = { ... barra , b : 4 }; // anular = { a: 1, c: 3, b: 4 }
Cuando ...
se utiliza en una declaración de función , indica un parámetro de descanso . El parámetro restante debe ser el último parámetro con nombre en la lista de parámetros de la función. Se le asignará un Array
que contenga 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 ) { consola . iniciar sesión ( c . longitud ); } foo ( 1 , 2 , 3 , 4 , 5 ); // "3" → c = [3, 4, 5] foo ( 'a' , 'b' ); // "0" → c = []
Los parámetros Rest son similares al objeto de Javascript arguments
, que es un objeto similar a una matriz que contiene todos los parámetros (con y sin nombre) en la llamada de función actual. arguments
Sin embargo, a diferencia de , los parámetros rest son Array
objetos verdaderos, por lo que métodos como .slice()
y .sort()
pueden usarse directamente en ellos.
Las variables que hacen referencia a objetos son iguales o idénticas sólo si hacen referencia al mismo objeto:
constante obj1 = { a : 1 }; constante obj2 = { a : 1 }; constante obj3 = obj1 ; consola . iniciar sesión ( obj1 == obj2 ); // consola falsa . iniciar sesión ( obj3 == obj1 ); // consola verdadera . iniciar sesión ( obj3 === obj1 ); //verdadero
Véase también Cadena.
JavaScript proporciona cuatro operadores lógicos:
NOT = !a
)OR = a || b
) y conjunción ( AND = a && b
)c ? t : f
)En el contexto de una operación lógica, cualquier expresión se evalúa como verdadera excepto lo siguiente :
""
, ''
,0
, -0
, NaN
,null
, undefined
,false
.La función booleana se puede utilizar para convertir explícitamente a una primitiva de tipo Boolean
:
// Sólo las cadenas vacías devuelven consola falsa . iniciar sesión ( booleano ( "" ) === falso ); consola . log ( booleano ( "falso" ) === verdadero ); consola . log ( booleano ( "0" ) === verdadero ); // Sólo cero y NaN devuelven una consola falsa . log ( booleano ( NaN ) === falso ); consola . iniciar sesión ( booleano ( 0 ) === falso ); consola . iniciar sesión ( booleano ( - 0 ) === falso ); // equivalente a -1*0 consola . log ( booleano ( - 2 ) === verdadero ); // Todos los objetos devuelven consola verdadera . log ( booleano ( este ) === verdadero ); consola . iniciar sesión ( booleano ({}) === verdadero ); consola . iniciar sesión ( booleano ([]) === verdadero ); // Estos tipos devuelven consola falsa . log ( booleano ( nulo ) === falso ); consola . log ( booleano ( indefinido ) === falso ); // equivalente a booleano()
El operador NOT evalúa su operando como booleano y devuelve la negación. Usar el operador dos veces seguidas, como doble negativo , convierte explícitamente una expresión en una primitiva de tipo booleano:
consola . iniciar sesión ( ! 0 === booleano ( ! 0 )); consola . iniciar sesión ( booleano ( ! 0 ) === !! 1 ); consola . iniciar sesión ( !! 1 === booleano ( 1 )); consola . iniciar sesión ( !! 0 === booleano ( 0 )); consola . iniciar sesión ( booleano ( 0 ) === ! 1 ); consola . iniciar sesión ( ! 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:
consola . iniciar sesión ([] == falso ); consola . iniciar sesión ([] ? Verdadero : falso ); // “verdadero”, pero la comparación usa la consola [].toString() . iniciar sesión ([ 0 ] == falso ); consola . iniciar sesión ([ 0 ] ? verdadero : falso ); // [0].toString() == "0" consola . iniciar sesión ( "0" == falso ); consola . iniciar sesión ( "0" ? Verdadero : falso ); // "0" → 0... (0 == 0)... 0 ← consola falsa . iniciar sesión ([ 1 ] == verdadero ); consola . iniciar sesión ([ 1 ] ? Verdadero : falso ); // [1].toString() == "1" consola . iniciar sesión ( "1" == verdadero ); consola . iniciar sesión ( "1" ? Verdadero : falso ); // "1" → 1 ... (1 == 1) ... 1 ← verdadera consola . iniciar sesión ([ 2 ] != verdadero ); consola . iniciar sesión ([ 2 ] ? Verdadero : falso ); // [2].toString() == consola "2" . iniciar sesión ( "2" ! = verdadero ); consola . iniciar sesión ( "2" ? Verdadero : falso ); // "2" → 2 ... (2 != 1) ... 1 ← verdadero
Las expresiones que utilizan características como post-incremento ( ) tienen un efecto secundarioi++
anticipado . JavaScript proporciona evaluación de cortocircuito de expresiones; el operando derecho sólo se ejecuta si el operando izquierdo no es suficiente para determinar el valor de la expresión.
consola . iniciar sesión ( a || b ); // Cuando a es verdadero, no hay razón para evaluar b. consola . iniciar sesión ( a && b ); // Cuando a es falso, no hay razón para evaluar b. consola . iniciar sesión ( c ? t : f ); // Cuando c es verdadera, 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:
consola . iniciar sesión ( a || b ); // si a es verdadero, devuelve a; en caso contrario, devuelve b console . iniciar sesión ( a && b ); // si a es falso, devuelve a; en caso contrario, devuelve b
Los programadores que están más familiarizados con el comportamiento en C pueden encontrar sorprendente esta característica, pero permite una expresión más concisa de patrones como la fusión nula :
constante s = t || "(por defecto)" ; // asigna t, o el valor predeterminado, si t es nulo, está vacío, etc.
JavaScript admite los siguientes operadores binarios bit a bit :
Ejemplos:
constante x = 11 y 6 ; consola . iniciar sesión ( x ); // 2
JavaScript admite el siguiente operador bit a bit unario :
JavaScript admite los siguientes operadores de asignación binaria:
Ejemplos:
sea x = 7 ; consola . iniciar sesión ( x ); // 7 x <<= 3 ; consola . iniciar sesión ( x ); // 7->14->28->56
Ejemplos:
let str = "ab" + "cd" ; // cadena "abcd" += "e" ; // "abcd" constante cadena2 = "2" + 2 ; // "22", no "4" o 4.
El operador más cercano a JavaScript es ??
, el "operador coalescente nulo", que se agregó al estándar en la undécima edición de ECMAScript . [14] En versiones anteriores, se podía utilizar a través de un complemento de Babel y en TypeScript . Evalúa su operando de la izquierda y, si el valor del resultado no es "nulo" ( null
o undefined
), toma ese valor como resultado; de lo contrario, evalúa el operando de la derecha y toma el valor resultante como resultado.
En el siguiente ejemplo, a
se le asignará el valor de b
si el valor de b
no es null
o undefined
, en caso contrario se le asignará 3.
constante a = b ?? 3 ;
Antes del operador coalescente nulo, los programadores usarían el operador lógico OR ( ||
). Pero donde ??
busca específicamente null
o undefined
, el ||
operador busca cualquier valor falso: ,,,,, null
y , por supuesto ,.undefined
""
0
NaN
false
En el siguiente ejemplo, a
se le asignará el valor de b
si el valor de b
es verdadero; de lo contrario, se le asignará 3.
constante a = b || 3 ;
Un par de llaves { }
y una secuencia adjunta de declaraciones constituyen una declaración compuesta, que se puede usar dondequiera que se pueda usar una declaración.
if ( expr ) { //declaraciones; } else if ( expr2 ) { //declaraciones; } else { //declaraciones; }
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 declaración if que selecciona una de dos declaraciones para ejecutar según una condición. Es decir, el operador condicional es para expresiones y si es para declaraciones.
resultado constante = condición ? expresión : alternativa ;
es lo mismo que:
if ( condición ) { const resultado = expresión ; } else { resultado constante = alternativa ; }
A diferencia de la declaración if , el operador condicional no puede omitir su "otra rama".
La sintaxis de la declaración de cambio de JavaScript es la siguiente:
switch ( expr ) { case ALGÚN VALOR : // declaraciones; romper ; case OTRO VALOR : // declaraciones para cuando OTRO VALOR || ORNAOTHERONE // declaración sin interrupción, pasando al siguiente caso case ORANOTHERONE : // declaraciones específicas de ORANOTHERONE (es decir, !ANOTHERVALUE && ORANOTHER); romper ; //La responsabilidad termina aquí. case YETANOTHER : // declaraciones; romper ; predeterminado : // declaraciones; romper ; }
break;
es opcional; sin embargo, normalmente es necesario, ya que de lo contrario la ejecución del código continuará hasta el cuerpo del siguiente bloque de caso. Este comportamiento de caída se puede utilizar cuando el mismo conjunto de declaraciones se aplica en varios casos, creando efectivamente una disyunción entre esos casos.La sintaxis del bucle for de JavaScript es la siguiente:
for ( inicial ; condición ; instrucción de bucle ) { /* las sentencias se ejecutarán cada vez que el bucle for{} realice un ciclo, mientras se cumpla la condición */ }
o
for ( inicial ; condición ; declaración de bucle ( iteración )) // una declaración
La sintaxis de JavaScript for ... in loop
es la siguiente:
for ( var nombre_propiedad en algún_objeto ) { // declaraciones usando algún_objeto[nombre_propiedad]; }
if (some_object.hasOwnProperty(property_name)) { ...
Array.prototype.newMethod = function() {...
for ... in
La sintaxis del bucle while de JavaScript es la siguiente:
mientras ( condición ) { declaración1 ; declaración2 ; declaración3 ; ... }
La sintaxis de JavaScript do ... while loop
es la siguiente:
hacer { declaración1 ; declaración2 ; declaración3 ; ... } mientras ( condición );
La declaración with agrega todas las propiedades y métodos del objeto dado al alcance del siguiente bloque, permitiendo hacer referencia a ellos como si fueran variables locales.
con ( documento ) { const a = getElementById ( 'a' ); const b = getElementById ( 'b' ); const c = getElementById ( 'c' ); };
La semántica es similar a la declaración with de Pascal .
Debido a que la disponibilidad de las declaraciones 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 un with adjunto ), esta declaración no está permitida en modo estricto .
JavaScript admite etiquetas anidadas en la mayoría de las implementaciones. Se pueden etiquetar bucles o bloques para la instrucción break y bucles para continue
. Aunque goto
es una palabra reservada, [15] goto
no está implementada en JavaScript.
bucle1 : for ( let a = 0 ; a < 10 ; ++ a ) { if ( a === 4 ) romper bucle1 ; // Se detiene después del cuarto intento console . iniciar sesión ( 'a =' + a ); bucle2 : for ( let b = 0 ; b < 10 ; ++ b ) { if ( b === 3 ) continuar bucle2 ; // El número 3 se omite si ( b === 6 ) continúa loop1 ; // Continúa el primer bucle, no se muestra 'terminado' en la consola . iniciar sesión ( 'b = ' + b ); } //fin de la consola loop2 . iniciar sesión ( 'terminado' ); } //fin del bucle1 bloque1 : { consola . iniciar sesión ( 'Hola' ); // Muestra el bloque de interrupción 'Hola' 1 ; consola . iniciar sesión ( 'Mundo' ); // Nunca llegaré aquí } goto block1 ; // Error de análisis.
Una función es un bloque con una lista de parámetros (posiblemente vacía) al que normalmente se le asigna un nombre. Una función puede utilizar variables locales. Si sale de la función sin una declaración de devolución, se devuelve el valor indefinido .
function gcd ( número1 , número2 ) { if ( isNaN ( número1 * número2 )) throw TypeError ( "No se permiten argumentos no numéricos." ); número1 = Matemáticas . ronda ( número1 ); número2 = Matemáticas . ronda ( número2 ); let diferencia = número1 - número2 ; si ( diferencia === 0 ) devuelve número1 ; ¿Diferencia de retorno > 0 ? mcd ( número2 , diferencia ) : mcd ( número1 , -diferencia ) ; } consola . iniciar sesión ( mcd ( 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 = mcd ; // mygcd y gcd hacen referencia a la misma función. consola . iniciar sesión ( mygcd ( 60 , 40 )); // 20
Las funciones son objetos de primera clase y pueden asignarse a otras variables.
El número de argumentos proporcionados al llamar a una función puede no corresponder necesariamente al número de argumentos en la definición de la función; un argumento con nombre en la definición que no tiene un argumento coincidente en la llamada tendrá el valor indefinido (que puede convertirse implícitamente en falso). Dentro de la función, también se puede acceder a los argumentos a través del objeto de argumentos ; esto proporciona acceso a todos los argumentos que utilizan índices (por ejemplo ), incluidos aquellos que superan el número de argumentos nombrados. (Si bien la lista de argumentos tiene una propiedad, no es una instancia de Array ; no tiene métodos como .slice() , .sort() , etc.)arguments[0], arguments[1], ... arguments[n]
.length
función agregar7 ( x , y ) { si ( ! y ) { y = 7 ; } consola . log ( x + y + argumentos . longitud ); }; agregar7 ( 3 ); // 11 agregar7 ( 3 , 4 ); // 9
Los valores primitivos (número, booleano, cadena) se pasan por valor. Para los objetos, es la referencia al objeto que se pasa.
constante obj1 = { a : 1 }; constanteobj2 = { b : 2 } ; función foo ( p ) { p = obj2 ; // Ignora el parámetro real p . b = argumentos [ 1 ]; } foo ( obj1 , 3 ); // No afecta a obj1 en absoluto. 3 es una consola de parámetros adicional . iniciar sesión ( ` ${ obj1 . a } ${ obj2 . b } ` ); // escribe 1 3
Las funciones se pueden declarar dentro de otras funciones y acceder a las variables locales de la función externa. Además, implementan cierres completos al recordar las variables locales de la función externa incluso después de que la función externa haya salido.
sea t = "Arriba" ; dejar bar , baz ; función foo () { let f = "foo var" ; barra = función () { consola . iniciar sesión ( f ) }; baz = función ( x ) { f = x ; }; } foo (); baz ( "argbaz" ); bar (); // "baz arg" (no "foo var") aunque foo() haya salido. consola . iniciar sesión ( t ); // Arriba
El operador de espera en JavaScript sólo se puede utilizar desde 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 se resuelva la promesa (a menos que se rechace la promesa, en cuyo caso se generará un error que se puede manejar con el manejo normal de excepciones de JavaScript ). Si el parámetro no es una promesa, el parámetro en sí se devolverá inmediatamente. [16]
Muchas bibliotecas proporcionan objetos de promesa que también se pueden usar con await, siempre que coincidan con la especificación de las promesas nativas de JavaScript. Sin embargo, las promesas de la biblioteca jQuery no eran compatibles con Promises/A+ hasta jQuery 3.0. [17]
Aquí hay un ejemplo (modificado de este artículo [18] ):
función asíncrona createNewDoc () { dejar respuesta = esperar db . correo ({}); // publicar un nuevo documento devolver db . obtener ( respuesta . id ); // buscar por id } función asíncrona principal () { intentar { dejar doc = esperar crearNuevoDoc (); consola . iniciar sesión ( doc ); } captura ( err ) { consola . iniciar sesión ( errar ); } } principal ();
Por conveniencia, los tipos normalmente se subdividen en primitivos y objetos . Los objetos son entidades que tienen una identidad (sólo son iguales a ellos mismos) y que asignan nombres de propiedades a valores ("ranuras" en terminología de programación basada en prototipos ). Los objetos pueden considerarse matrices asociativas o hashes y, a menudo, se implementan utilizando estas estructuras de datos. Sin embargo, los objetos tienen características adicionales, como una cadena prototipo , que las matrices asociativas ordinarias no tienen.
JavaScript tiene varios tipos de objetos integrados, a saber Array
, Boolean
, Date
, Function
, Math
, Number
, Object
y RegExp
. String
Otros objetos son "objetos host", definidos no por el lenguaje, sino por el entorno de ejecución. Por ejemplo, en un navegador, los objetos de host típicos pertenecen al DOM (ventana, formulario, enlaces, etc.).
Los objetos se pueden crear utilizando un constructor o un objeto literal. El constructor puede utilizar una función de objeto incorporada o una función personalizada. Es una convención que las funciones constructoras reciban un nombre que comience con una letra mayúscula:
// Constructor const anObject = nuevo objeto (); // Objeto literal const objectA = {}; objeto constanteA2 = { }; // A != A2, {}s crea nuevos objetos como copias. const objetoB = { índice1 : 'valor 1' , índice2 : 'valor 2' }; // Constructor personalizado (ver más abajo)
Los literales de objetos y los literales de matriz permiten crear fácilmente estructuras de datos flexibles:
const miEstructura = { nombre : { primero : "Mel" , último : "Smith" }, edad : 33 , pasatiempos : [ "ajedrez" , "trotar" ] };
Esta es la base de JSON , que es una notación simple que utiliza una sintaxis similar a JavaScript para el intercambio de datos.
Un método es simplemente una función que se ha asignado a un nombre de propiedad de un objeto. A diferencia de muchos lenguajes orientados a objetos, no existe distinción entre una definición de función y una definición de método en JavaScript relacionado con objetos. Más bien, la distinción ocurre durante la llamada a la función; una función se puede llamar como método.
Cuando se llama como método, la variable local estándar this se establece automáticamente en la instancia del objeto a la izquierda de " . ". (También existen métodos de llamada y aplicación que pueden configurar esto explícitamente; algunos paquetes como jQuery hacen cosas inusuales con esto ).
En el siguiente ejemplo, Foo se utiliza como constructor. No hay nada especial en un constructor: es simplemente una función simple que inicializa un objeto. Cuando se usa con la nueva palabra clave, como es la norma, se establece en un objeto en blanco recién creado.
Tenga en cuenta que en el siguiente ejemplo, Foo simplemente asigna valores a las ranuras, algunas de las cuales son funciones. Por tanto, puede asignar diferentes funciones a diferentes instancias. No hay ningún prototipo en este ejemplo.
función px () { devuelve esto . prefijo + "X" ; } función Foo ( yz ) { esto . prefijo = "a-" ; si ( yz > 0 ) { esto . pyz = función () { devolver esto . prefijo + "Y" ; }; } más { esto . pyz = función () { devolver esto . prefijo + "Z" ; }; } este . m1 = píxeles ; devolver esto ; } const foo1 = nuevo Foo ( 1 ); const foo2 = nuevo Foo ( 0 ); foo2 . prefijo = "b-" ; consola . log ( "foo1/2 " + foo1 . pyz () + foo2 . pyz ()); // foo1/2 aY bZ foo1 . m3 = píxeles ; // Asigna la función en sí, no su resultado evaluado, es decir, no px() const baz = { "prefix" : "c-" }; baz . m4 = píxeles ; // No es necesario un constructor para crear un objeto. consola . log ( "m1/m3/m4 " + foo1 . m1 () + foo1 . m3 () + baz . m4 ()); // m1/m3/m4 aX aX cX foo1 . m2 (); // Lanza una excepción porque foo1.m2 no existe.
Las funciones constructoras simplemente asignan valores a las ranuras de un objeto recién creado. Los valores pueden ser datos u otras funciones.
Ejemplo: manipulación de un objeto:
función MiObjeto ( atributoA , atributoB ) { this . atributoA = atributoA ; este . atributoB = atributoB ; } MiObjeto . estáticoC = "azul" ; // En la función MyObject, no en la consola de objetos . iniciar sesión ( MiObjeto . staticC ); // azul objeto constante = nuevo MiObjeto ( 'rojo' , 1000 ); consola . log ( objeto . atributoA ); // consola roja . log ( objeto . atributoB ); // 1000 consola . iniciar sesión ( objeto . staticC ); // objeto indefinido . atributoC = nueva Fecha (); //agregar una nueva propiedad eliminar objeto . atributoB ; // eliminar una propiedad del objeto console . log ( objeto . atributoB ); // indefinido
Se hace referencia al constructor en sí en la ranura del constructor del prototipo del objeto . Entonces,
function Foo () {} // El uso de 'nuevos' establece espacios de prototipo (por ejemplo, // x = new Foo() establecería el prototipo de x en Foo.prototype, // y Foo.prototype tiene un espacio de constructor que apunta hacia Foo). constante x = nuevo Foo (); // Lo anterior es casi equivalente a const y = {}; y . constructor = Foo ; y . constructor (); // Excepto x . constructor == y . constructor ; // verdadero x instancia de Foo ; // verdadero y instancia de Foo ; // false // el prototipo de y es Object.prototype, no // Foo.prototype, ya que se inicializó con // {} en lugar del nuevo Foo. // Aunque Foo está configurado en la ranura del constructor de y, // esto es ignorado por instancia de - sólo se considera la // ranura del constructor del prototipo de y .
Las funciones son objetos en sí mismos, que pueden usarse para producir un efecto similar a las "propiedades estáticas" (usando la terminología C++/Java) como se muestra a continuación. (El objeto de función también tiene una prototype
propiedad especial, como se analiza en la sección "Herencia" a continuación).
La eliminación de objetos rara vez se utiliza, ya que el motor de secuencias de comandos recolectará objetos a los que ya no se hace referencia.
JavaScript admite jerarquías de herencia mediante la creación de prototipos a la manera de Self .
En el siguiente ejemplo, la clase Derivada hereda de la clase Base . Cuando d se crea como Derivado , 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 queda claro cambiando el valor de base.aBaseFunction , que se refleja en el valor de d.aBaseFunction .
Algunas implementaciones permiten acceder al prototipo o configurarlo explícitamente utilizando la ranura __proto__ como se muestra a continuación.
función Base () { esto . anOverride = función () { consola . iniciar sesión ( "Base::anOverride()" ); }; este . aBaseFunction = función () { consola . iniciar sesión ( "Base::aBaseFunction()" ); }; } función Derivada () { this . anOverride = función () { consola . log ( "Derivado::anOverride()" ); }; } base constante = nueva Base (); Derivado . prototipo = base ; // Debe estar antes de new Derived() Derived . prototipo . constructor = Derivado ; // Requerido para que `instanceof` funcione const d = nuevo Derivado (); // Copia Derived.prototype en la ranura de prototipo oculta de la instancia d. d instancia de Derivado ; // verdadero d instancia de Base ; // verdadero base . aBaseFunction = función () { consola . iniciar sesión ( "Base::aNEWBaseFunction()" ); }; d . una anulación (); // Derivado::anOverride() d . unaFunciónBase (); // Base::aNEWBaseFunction() consola . log ( d . aBaseFunction == Derivado . prototipo . aBaseFunction ); // verdadero consola . iniciar sesión ( 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 prototipos en la creación de una instancia, pero 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 . prototipo . metro = m2 ; barra constante = nueva Base (); consola . log ( "barra.m " + barra .m ( )); // bar.m Dos función Arriba () { esto . metro = m3 ; } const t = nuevo Top (); const foo = nueva Base (); Base . prototipo = t ; // No hay efecto en foo, se copia la *referencia* a t. consola . iniciar sesión ( "foo.m " + foo . m ()); // foo.m Dos const baz = nueva Base (); consola . iniciar sesión ( "baz.m " + baz . m ()); // baz.m Tres t . metro = m1 ; // Afecta a baz y a cualquier otra clase derivada. consola . iniciar sesión ( "baz.m1 " + baz . m ()); // baz.m1 Uno
En la práctica se utilizan muchas variaciones de estos temas, y pueden resultar poderosas y confusas.
JavaScript incluye una declaración try ... catch ... finally
de manejo de excepciones para manejar errores en tiempo de ejecución.
La try ... catch ... finally
declaración detecta excepciones resultantes de un error o una declaración de lanzamiento. Su sintaxis es la siguiente:
try { // Declaraciones en las que se pueden generar excepciones } catch ( errorValue ) { // Declaraciones que se ejecutan en caso de una excepción } finalmente { // Declaraciones que se ejecutan después en cualquier sentido }
Inicialmente, se ejecutan las declaraciones dentro del bloque try. Si se produce una excepción, el flujo de control del script se transfiere inmediatamente a las declaraciones en el bloque catch, con la excepción disponible como argumento de error. De lo contrario, se omitirá el bloque de captura. El bloque catch puede throw(errorValue) si no quiere manejar un error específico.
En cualquier caso, las sentencias del bloque finalmente siempre se ejecutan. Esto se puede utilizar para liberar recursos, aunque la memoria se recolecta automáticamente como basura.
Se puede omitir la cláusula catch o finalmente. El argumento catch es obligatorio.
La implementación de Mozilla permite múltiples declaraciones catch, como una extensión del estándar ECMAScript. Siguen una sintaxis similar a la utilizada en Java :
prueba { declaración ; } catch ( e if e == "InvalidNameException" ) { declaración ; } catch ( e if e == "InvalidIdException" ) { declaración ; } catch ( e if e == "InvalidEmailException" ) { declaración ; } captura ( e ) { declaración ; }
En un navegador, el evento onerror se usa más comúnmente para detectar excepciones.
onerror = función ( valorError , URL , número de línea ) {...; devolver verdadero ;};
Evalúa el primer parámetro como una expresión, que puede incluir declaraciones de asignación. La expresión puede hacer referencia a las variables locales de las funciones. Sin embargo, eval
representa un riesgo de seguridad importante, ya que permite que un mal actor ejecute código arbitrario, por lo que se desaconseja su uso. [20]
> ( function foo () { ... var x = 7 ; ... console . log ( "val " + eval ( "x + 2" )); ... })(); valor 9 indefinido
Omitir punto y coma no es una buena práctica de programación; deberías acostumbrarte a insertarlos.
En JavaScript, se puede declarar una variable después de haber sido utilizada. En otras palabras; una variable se puede utilizar antes de haber sido declarada.