La jerarquía del lenguaje se divide en:
JS no tiene tipos de datos, pero sí se pueden distinguir cinco categorías de tipos de datos implícitos:
Enteros de 32 bits en decimal, octal (0...) o hexadecimal (0x...). Ej.: -25, 0777, 0xFF.
Reales en notación normal o científica. Ej.: 35.709, -1.045e7
Entre comillas (") o apóstrofos ('). Permite apótrofos dentro de comillas y viceversa. Cadena vacía "" o ''.
Secuencias de escape: \t (horiz tab, ASCII 9), \n (return), \r (line feed, ASCII 13), \f (form feed, ASCII 10), \b (backspace).
El carácter '\' también se utiliza para anular el significado que tienen determinados caracteres: \' (carácter apóstrofo), \" (carácter comillas). El carácter '\' al final de una línea anula el significado del carácter de salto de línea, lo que sirve por ejemplo para continuar una cadena en la línea siguiente.
Valores true y false. En realidad JS los convierte internamente a 1 y 0 respectivamente, pero se recomienda no utilizarlo (incluso cualquier valor distinto de 0 es interpretado como true).
Una expresión con una variable no inicializada da error, pero si la variable se inicializa a null, asume los valores 0, "" o false según se convierta a número, cadena o lógico.
En las conversiones implícitas, siempre intenta convertir de izquierda a derecha. Así, 5+"10"=15 (suma), "Hola"+10="Hola10" (concatenación), pero 5+"Hola" da error. Podemos observar que el operador "+" está sobrecargado (overloading).
Dintingue mayúsculas y minúsculas. Deben comenzar por letra, subrayado (_) o dólar ($), seguido de letras, números y subrayados (_). En principio nombres de cualquier número de caracteres. Como siempre, se recomienda seguir la Notación Húngara. Ej.: nSumaTotalBeneficios, sTituloVentana.
La sintaxis para declarar una variable es:
var nombre [= expresión|null] [,...]
Si no se inicializa una variable, tiene un valor especial: undefined. En realidad no es necesario declarar las variables, pero se recomienda declararlas siempre. Por otra parte, al no existir tipos, es posible hacer x=10 y más tarde x="Hola", pero no es una buena práctica.
Cualquier variable no declarada que aparezca dentro o fuera de una función se considera global, aunque para que sea conocida debe ejecutarse la sentencia en la que aparece dicha variable. Por eso es una mala práctica no declarar las variables.
Cada sentencia termina en final de línea, pero se pueden incluir varias sentencias en una misma línea separadas por ";". En cualquier caso, es recomendable terminar todas las sentencias con ";" para evitar confusiones. Distingue entre mayúsculas y minúsculas.
Aritméticos | |
---|---|
+ | Suma, Concatenación (o Positivo unario) |
- | Resta (o Negativo unario) |
* | Multiplicación |
/ | División |
% | Módulo |
++ | Pre/postincremento (unario) |
-- | Pre/postdecremento (unario) |
Lógicos | |
==, != | Igualdad, Desigualdad |
<,<=, =>, > | Menor/Mayor/Igual |
! | Negación |
&&, || | Relacionales |
?: | Condicional (ternario) |
, | Concatenación Lógica |
De Bits | |
&, | | AND, OR |
^ | XOR |
~ | NOT (complemento a 1) |
<<, >>, >>> | Desplazamiento Izdo., Dcho. y Dcho. Sin Signo |
De Asignación y Agregación | |
= | Asignación |
op= | Agregación (+ - * / % & | ^ ~ << >> >>>) |
El operador "+" también funciona como Operador de Concatenación de Cadenas.
El tipo del resultado de una expresión promociona para obtener la mayor precisión, excepto en el caso de la división entera. Así, 10/4=2, mientras que 10/4.0=2.5.
El signo del resultado del módulo siempre es el mismo que el cociente. Así, si -21/4=-5, entonces -21%4=-1.
Comparan enteros, reales o cadenas (distinguen mayúsculas y minúsculas), pero se recomienda no utilizarlos con reales. Ej.: if (z == 3.0) podría devolver un resultado distinto dependiendo de cada máquina.
Comparan enteros, reales o cadenas (distinguen mayúsculas y minúsculas). En el caso de cadenas, una cadena es menor que otra si va antes alfabéticamente.
Invierte el resultado de una comparación.
Permiten combinar varias expresiones de comparación
JS deja de evaluar una expresión lógica en cuanto conoce el valor resultante de la misma. Así, la expresión if (x == 5 && y == 6 && z == 7) dejará de evaluarse en cuanto no se cumpla alguna de las tres comparaciones (ya que en ese caso el resultado será falso), y la expresión if (x == 5 || y == 6 || z == 7) dejará de evaluarse en cuanto se cumpla alguna de las tres comparaciones (ya que en ese caso el resultado será cierto).
En el caso de comparaciones de igualdad o desigualdad de reales, en vez de hacer if (x != 3.0, se podría utilizar if (x-3.0) < epsilon || (3.0-x) < epsilon, siendo epsilon un valor pequeño, por ejemplo 0.001. De todas formas lo mejor es no realizar este tipo de comparaciones con reales.
Operador condicional: condición ? expr_si_cierto : expr_si_falso devuelve la primera expresión si la condición es cierta y la segunda si es falsa.
Operador coma: expr1, expr2, ..., exprn evalúa todas las expresiones y devuelve el resultado de la última.
Siempre se deben utilizar con números enteros.
El operador "<<" equivale a multiplicar por 2, y el operador ">>" equivale a dividir por 2. El primero rellena con ceros por la derecha, mientras que el segundo rellena con el bit de signo por la izquierda. El operador ">>>" equivale a ">>" pero rellenando con ceros por la izquierda (se pierde el signo).
Los operadores de agregación son más eficientes. Así, x += 10 es más eficiente que x=x+10 porque en el primer caso sólo se accede una vez a la dirección de la variable "x" en memoria.
Estilo C con /* ... */ (varias líneas) o estilo C++ con //... (hasta fin de línea).
Las estructuras de control permiten ejecutar una instrucción o un bloque de instrucciones {...} bien sea de forma condicionada o bien de forma repetitiva.
if (condición) ... [else ...]
while (condición) ...
for ([lista_inicializaciones]; [condición]; [lista_actualizaciones]) ...
Termina inmediatamente la ejecución de un bucle.
Termina inmediatamente la iteración actual.
function nombre([lista_parámetros_por_valor]) { [var lista_variables_locales;] ... [return valor_devuelto;] }
El nombre sigue los mismos convenios que para las variables.
Las funciones se pueden crear en un fichero (normalmente con extensión .js) y cargarse cuando sean necesarias mediante el atributo SRC="fichero.js" del tag SCRIPT.
Cuando se utiliza una librería de funciones en un "frame", todos los demás "frames" disponen automáticamente una variable llamada funcs que hace referencia al "frame" que contiene las funciones. Así, desde otro "frame" se podría llamar a una función de la librería en la forma funcs.función(...).
Un objeto consta de "propiedades" (variables internas) y "métodos" (funciones internas), y puede producir "eventos".
En principio todas las propiedades y métodos son públicos, aunque algunas propiedades son de sólo lectura (no se les puede asignar un valor). Para acceder a una propiedad o llamar a un método se utiliza la forma:
objeto.propiedad objeto.método(lista_argumentos)
Nota: aquí habla de "Objetos" e "Instancias de Objetos" en lugar de "Clases" e "Instancias de Clases".
Definir un objeto (clase) consiste simplemente en definir el "constructor de la clase" y definir todas sus propiedades mediante el cualificador this. Ej.:
function house(rms, stl, yr, gar) { this.rooms = rms; //number of rooms (integer) this.style = stl; //style: Colonial, Tudor, Ranch (string) this.yearbuilt = yr; //year built (integer) this.hasgarage = gar; //has a garage? (boolean) }
Es obligatoria la utilización de this, ya que en otro caso se interpretarían como variables locales. No es obligatorio declarar parámetros en el constructor: bastaría con inicializar las propiedades con unos valores por defecto.
Para crear instancias:
var Casa1=new house(); //Todas las propiedades "undefined". var Casa2=new house(10, "Colonial", 1989, true); //Todas definidas. var Casa3=new house(10, "Colonial"); //Estilo y garaje "undefined". var Casa3=new house(10, , 1980, 1); //¡ERROR! var Casa3=new house(10, null, 1980, 1); //Estilo con valor "null". var Casa3=new house(10, "", 1980, 1); //Estilo con valor "".
Los arrays se definen mediante la clase Array:
var nombre=new Array(número_de_elementos)
El índice comienza en cero. Los elementos pueden ser de distinto tipo y de cualquier tipo, incluso objetos, y se asignan como cualquier otra variable. Incluso se pueden definir nuevos elementos sobre la marcha:
var a=new Array(3); a[0]="Juan"; a[1]="Pedro"; a[2]="Rosa"; ... a[3]="Javier"; a[4]="María"; //¡Nuevos elementos!
Las propiedades de un objeto se almacenan en forma de array. Ej.:
var Casa=new house(10, "Colonial", 1989, true); for (var i=0; i != 4; i++) //Escribir las 4 propiedades. document.write(Casa[i], " ");
Es posible acceder al array de propiedades no sólo por índice, sino también por nombre de propiedad. Ej.:
var Casa=new house(10, "Colonial", 1989, true); document.write("Nº de habitaciones: ", Casa["rooms"]); document.write("Garaje: ", Casa["hasgarage"] ? "Sí" : "No");
Es posible añadir nuevas propiedades a una instancia sin más que asignar nuevos valores:
var Casa=new house(10, "Colonial", 1989, true); var Casa1=new house(8, "Ranch", 1990, true); Casa.nbath=2; //Nueva propiedad posición 4: nº de baños.
Esta propiedad no afecta a Casa1 ni a cualquier nueva instancia de house que se cree. Por supuesto, esto es una mala práctica que no se debe utilizar.
Debido a que un objeto es un array de propiedades, es posible definir una clase con un número variable de propiedades, es decir, un array de longitud variable:
function stringarr(howmany, initstr) { this.length = howmany; //Elemento 0 con el nº de elementos. for( var i = 1; i <= howmany; i++ ) this[i] = initstr; //Todos con el mismo valor inicial. } ... aStr = new stringarr(10, "spoon"); //10 cucharas... ... //Añadir nuevos elementos: aStr[101] = "I'm"; aStr[102] = "doing"; aStr[103] = "laundry"; aStr.length += 3;
Permite recorrer los nombres de todas las propiedades de una instancia:
for(var p in Casa) document.write("Propiedad ", p, "con valor ", Casa[p], "
");
Los métodos se declaran como propiedades, asignando a las mismas el nombre de una función definida aparte. La función puede tener o no el mismo nombre que el método. Dentro de la función se hace referencia al objeto mediante el cualificador this:
function house(rms, stl, yr, gar) //Clase "house". { this.rooms = rm; this.style = stl; this.yearbuilt = yr; this.hasgarage = garp; this.show = showhouse; //Método "show()" this.howold = howold; //Método "howold()" } function showhouse() //Escribir valores. { for(var p in this) { //No mostrar los métodos. var s=""+this[p]; //Convertir a cadena. if (s.substr(0, 8) != "function") document.write("<B>", p, ": </B>", this[p], "<BR>"); } } function howold(curyear) //Edad de la casa. { return curyear-this.yearbuilt; }
Una propiedad de un objeto puede a su vez contener una instancia de otro objeto. Así, document es una propiedad de window que contiene el documento que aparece en la ventana, window.document, y a su vez se puede acceder a las propiedades y métodos de dicha instancia: window.document.bgColor, window.document.write(), etc.
Evita escribir "objeto." delante de cada propiedad. Es menos eficiente porque JS ha de resolver cada referencia a una variable para ver si se trata de una propiedad o de una variable local.
with (instancia) { ... prop = expr; ... función(... prop ...); ... }
Una función en JS se almacena en realidad como un objeto que tiene dos propiedades, a las cuáles se puede acceder dentro de la propia función:
La propiedad arguments permite por tanto llamar a una función pasando todos los argumentos que se deseen. Ej.:
function Resultado(sMsj) //Devuelve cadena "sMsj: suma". { var nSuma=0; /* Sumar argumentos (excepto el 0 que es sMsj) */ for (var i=1; i != Resultado.arguments.length; i++) nSuma += Resultado.arguments[i]; return sMsj + ": " + nSuma; }
El usuario puede realizar una acción sobre un objeto de una página HTML. El objeto reacciona produciendo un determinado evento al cuál es posible asociar una función o manejador que se ejecutará automáticamente al producirse dicho evento.
En todos estos casos se carga o descarga una página, produciéndose los correspondientes eventos load y unload.
Otros eventos relacionados son mouseover, al situar el puntero sobre un enlace, y statechange, que indica que un objeto está realizando alguna operación pero aún no está listo para visualizarse (por ej., se está cargando un plug-in de vídeo pero aún no está listo para visualizarse).
Existen cinco tipos de botones:
Algunos eventos son click, al hacer clic en el botón, y submit, al enviar el formulario mediante el botón Submit.
Los botones ocultos no producen eventos
Existen tres tipos de cuadros de texto:
Algunos eventos son: change, al modificar su contenido, select, al seleccionar texto, focus, al situarse en el campo (el campo obtiene el "foco" de atención), y blur, cuando el campo pierde el "foco".
Los campos de tipo Password no producen eventos para evitar el acceso a los mismos.
Producen los eventos focus, blur y change. Da igual que sean normales o de selección múltiple
Desplazar (scroll) una ventana, leer un grupo de noticias, responder un e-mail, crear una entrada en favoritos, redimensionar o mover la ventana, etc.: ninguna de estas acciones afecta a la página actual.
Utilizar los botones Atrás, Adelante o Inicial del navegador no son realmente eventos de JS, pero generan eventos asociados a la página actual ya que descargan ésta.
Dado un elemento HTML (definido en su correspondiente tag) y dado un determinado evento que puede producir dicho elemento, para asociar una función o manejador a dicho evento se añade un nuevo atributo en el tag con el nombre onEvento, con la siguiente sintaxis:
<elemento ... onEvento="código_en_línea|función([argumentos])">
Los eventos se pueden producir a tres niveles: a nivel de documento, a nivel de formulario y a nivel de elemento de formulario.
En el tag BODY se pueden definir manejadores mediante los atributos onLoad y onUnload.
También se puede considerar a nivel de documento el tag A con el atributo onMouseOver cuando se sitúa el puntero sobre un enlace, y el atributo onClick cuando se selecciona el enlace.
Atributo onSubmit en el tag FORM (también se podría hacer con el atributo onClick en el botón Submit del formulario). La función de evento ha de devolver true o false según haya o no que enviar el formulario.
En los botones, atributo onClick; en los cuadros de texto, atributos onFocus, onBlur, onSelect y onChange; en los cuadros de lista, atributos onFocus, onBlur y onSelect.