JavaScript: Introducción básica a su sintaxis.

Este es el segundo post de la serie acerca del lenguaje JavaScript, el primero puedes encontrarlo haciendo clic aquí.

Haremos un recorrido introductorio por la sintaxis básica del lenguaje. Veremos que es un lenguaje sencillo, pero expresivo.

JavaScript no es Java:

Aunque el nombre incluye la palabra y JavaScript tiene influencia de la sintaxis de lenguajes como C y Java, son lenguajes totalmente diferentes, diseñados por personas diferentes, con objetivos diferentes. Conceptualmente Java es un lenguaje estático, donde el compilador chequea los tipos de datos y además es un lenguaje interpretado. JavaScript es dinámico, existen los tipos, pero solo se resuelven en runtime, y no es un lenguaje interpretado. JavaScript tiene mas influencia del lenguaje Scheme.

JavaScript es en general un lenguaje sencillo aunque expresivo, que ha triunfado donde Java ha fallado, en el cliente, y tiene la ventaja de que no necesita de instalación, y está presente en todos los browsers, por tanto en todos los PCs que se conectan a internet para navegar por la red.

Un poco de historia:

JavaScript fue desarrollado en los laboratorios de Netscape por Brendan Eich. Su objetivo era crear un lenguaje de scripts ligero capaz de ejecutarse en el browser Navigator II. Se tornó popular porque todos los programadores web de alguna forma necesitaron usarlo. Se generó mucha documentacion mala del lenguaje, enfocada en resolver temas puntuales, por tanto era visto como un lenguaje procedural cuando en realidad es totalmente orientado a objeto. Revisaremos la especificación 3 de ECMAScript o JavaScript 1.5, aunque desde el año 1999 se escribe la especificación 4 de ECMAScript, y aun no sale la revisión completa, un PDF de 40 páginas con las cosas nuevas pueden encontrarlo en http://www.ecmascript.org/es4/spec/overview.pdf

Sintáxis:

Tipos de datos primitivos:

Existen 3 tipos primitivos:
– boolean: tiene dos valores (true, false)
– number (puntos flotantes de 64 bits, e incluyen el valor especial NaN [not a number], y el especial Infinity
– string (Secuencia de cero o más caracteres Unicode. el tipo “character” no existe, un “character” es un string de tamaño 1. Los literales en string son string delimitados por los caracteres ‘ ‘ o entonces ” “, pueden ser usados ambos.

Para cada tipo primitivo existe un wrapper (cascaron) de tipo object, al cual le podemos agregar metodos, que podemos luego invocar en los tipos primitivos, esto es posible porque JavaScript hace una conversion automatica al wrapper del primitivo. Por ejemplo, es posible hacer algo como:

Number.alert = function () { alert(this.valueOf()) };
var i = 3;
i.alert(); // aqui ocurre una conversion automatica de number a Number
           // y se ejecuta la function alert de Number

Lo mismo ocurre para boolean cuyo wrapper es Boolean y string cuyo wrapper es String

Especiales:
null
undefined

Todos los demás son especializaciones del tipo object

Tipo de datos object:

Luego de los tipos simples que hemos visto, todo lo demás en JavaScript son objetos, que directa o indirectamente son especializaciones de Object.

Un objeto en JavaScript es un mapa (Map, par llave/valor), donde la llave(que siempre son string, por tanto si no lo son JavaScript lo convierte) es el nombre del atributo y su valor puede ser un tipo simple o un Object (por ejemplo una funcion)

Ejemplo:

var myObj = {};

Aqui se creó un nuevo objeto {} y se asigno una referencia (en memoria) a la varible llamada myObj.

Como pueden ver y a diferencia con lenguajes como C++ o Java, en JavaScript no se especifica el tipo del objeto a la hora de crearlo, lo que hace el lenguaje es pasar una referencia a la variable que apunta en memoria a la tabla de atributos y metodos del objeto.

Por otro lado JavaScript (v 1.5) “no contiene” clases (al menos como tipo), y los objetos pueden ser modificados en runtime agregando nuevos atributos o metodos, por ejemplo:

myObj.value = "Valor";

Los atributos pueden ser luego invocados usando notacion clasica o sea mediante el “.”

alert(myObj.value);

es posible tambien agregar, remplazar o obtener el valor de un atributo usando notacion mediante “[]”

alert(myObj["value"]);

Como un objeto es un mapa, es posible recorrer sus atributos dentro de un for:

for (attr in myObj) {
    alert("atributo: " + attr + ", valor : " + myObj[attr]);
}

En su forma literal los atributos se separan por comma, y su valor por “:”

var myObj = {
    nombre : "Jorge",
    apellido : "Rodriguez",
    edad : 32,
    saludo : function () {
        return "Hola, soy " + this.nombre;
    }
}

Arrays

Los arreglos en JavaScript son listas de datos simples u objetos, que crecen automaticamente mientras se agregan nuevos items. Tienen un atributo length, que determina la cantidad de items que contienen el arreglo, sin embargo el primer indice del arreglo es 0.

var myArr = [] // literal, array vacio
myArr = new Array() //mediante constructor
myArr = [1, 2, 3]; // arreglo de numbers
var dias = ["Lunes", "Martes", "Miercoles", "Jueves", "Viernes",
            "Sabado", "Domingo"];
dias[0] // Lunes
dias[6] // Domingo
dias.length // 7
var arrObjs = [
    {
        name : "metodo1",
        exec : function () { return 0 }
    },
    {
        name : "metodo2",
        exec : function (param) { return param + 1 }
    },
]

Funciones

Una función es un objeto de tipo Function, esto significa que puede estar presente en todas partes donde puede estar presente cualquier objeto, como han podido ver en los ejemplos anteriores.

En su defininión no necesita declarar los argumentos, aunque puede nombrarlos para posteriores referencias. Existe una variable especial local a la función llamada “arguments” que es el Array de los valores pasados a la funcion. Por ejemplo:

// forma literal para crear un objeto Function
var f = function () {
// no es obligatorio declarar parametros
    for (var i = 0; i < arguments.length; i++) {
        alert(arguments[i]); // arguments es una variable especial de
                             // tipo Array, que contiene a lista de
                             // argumentos
    }
}

Los argumentos que se declaren y no se pasan en la invocación son inicializados como undefined

Es posible declarar funciones anónimas:

call(function () {...}) // aqui se declaró una función anónima y se pasó
                        // como argumento en la invocación de la función call()

Funciones como constructores

Una Function puede ser usada para constuir instancias de objetos. para esto la funcion debe inicializar los datos de un objeto. Por Ejemplo

function Persona(nombre) {
    this.nombre = nombre;
    this.saluda = function () { return "Hola, mi nombre es " + nombre };
}

// para construir objetos instancias de Persona, inicializando con el atributo nombre y el método saluda

var u = new Persona('Jorge Rodriguez');
u.saluda() // retorna Hola, mi nombre es Jorge Rodriguez

Como pueden ver, de esta forma es posible simular las clases de Java.

Las variables en JavaScript siempre tienen que retornar algo, para aquellas que no retornen nada automaticamente el lenguaje retorna undefined

Variables:

Las variables no necesitan de un tipo, basta con colocar un nombre y asignarle un valor, en este caso son globales, si se quiere definir una variable con un scope limitado debe usarse el identificador var.

x = "GLOBAL";
function local() {
    var local = 1; // local no existe fuera del scope de la funcion,
                   // solo para local y las funciones inner
    function inner() {
        local = local + 1; // valido
    };
}
local = local + 1; // invalido, local no existe aca

Sentencias:

Las sentencias if, switch, for, while, fueron copiadas del lenguaje C

IF:

if (x == 1) {
    // si x es 1
}
if (x == 1) {
    // si x es 1
} else {
    // de lo contrario
}
if (x == 1) {
    // si x es 1
} else if (x == 2) {
    // sino si x = 2
} else {
    // si x tiene otro valor que no es 1 o 2
}

SWITCH:

En switch variable puede ser cualquier tipo de dato, a diferencia de Java donde variable tiene que ser un numero.

switch (variable) {
    case "ok":
        // si variable == "ok"
        break;
    case 1:
        // si variable == "ok"
        break;
    default:
        break;
}

FOR:

var reg_encontrado = false;
for (var i = 0; !reg_encontrado && i < registros.length; i++) {
    reg_encontrado == registros[i] == "Jorge";
}

WHILE:

var reg_encontrado = false;
var i = 0;
while (!reg_encontrado && i < registros.length) {
    reg_encontrado = registros[i] == "Jorge";
    i = i + 1;
}

DO:

var reg_encontrado = false;
var i = 0;
do {
    reg_encontrado = registros[i] == "Jorge";
    i = i + 1;
} while (!reg_encontrado && i < registros.length);

La única diferencia entre while y do while, es que en do while la sentencia se va a ejecutar al menos 1 vez siempre.

Operadores:

Operadores de Asignación:

Un operador de asignación asigna un valor a su operando izquierdo basándose en el valor de su operando derecho. El operador básico de asignación es el igual (=), el cual asigna el valor de su operador derecho a su operador izquierdo. Esto es, x=y asigna el valor de y a x.

El resto de operadores de asignación son abreviaturas de operaciones estándar, como se muestra en la siguiente tabla.
Operador abreviado     Significado

x += y                 x = x + y
x -= y                 x = x – y
x *= y                 x = x * y
x /= y                 x = x / y
x %= y                 x = x % y
x <<= y             x = x << y
x >>= y             x = x >> y
x >>>= y             x = x >>> y
x &= y                 x = x & y
x ^= y                 x = x ^ y
x |= y                 x = x | y

Operadores de comparación

Un operador de comparación compara sus operandos y devuelve un valor lógico en función de si la comparación es verdadera. Los operandos pueden ser valores numéricos, de cadena de caracteres, lógicos u objetos. Las cadenas se comparan basandose en el orden lexicográfico estándar, usando los valores Unicode. Si dos operandos no son del mismo tipo, JavaScript intentará convertir los operandos a un tipo apropiado para la comparación, excepto para los operandos === y !==. Esto acostumbra a resultar en una comparación numérica. La siguiente tabla describe los operadores de comparación.

Distinto (!=)     Devuelve true si los operandos no son iguales.
Igual estricto (===)     Devuelve true si los operandos son iguales y del mismo tipo.
Distinto estricto (!==)     Devuelve true si los operandos no son iguales y/o no son del mismo tipo.
Mayor que (>)     Devuelve true si el operando izquierdo es mayor que el derecho.
Mayor o igual que (>=)     Devuelve true si el operando izquierdo es mayor o igual que el derecho.
Menor que (<)     Devuelve true si el operando izquierdo es menor que el derecho.
Menor o igual que (<=)     Devuelve true si el operando izquierdo es menor o igual que el derecho.

Operadores aritméticos:

Los operadores aritméticos toman valores numéricos (tanto literales como variables) como operandos y devuelven un único valor numérico. Los operadores aritméticos estándar son el de suma (+), el de resta (-), el de multiplicación (*) y el de división (/). Estos operadores trabajan igual que en la mayoría de lenguajes de programación, excepto el operador / que devuelve la división real (de coma flotante), no la división entera como sucede en C o en Java. Por ejemplo:

1/2 //devuelve 0.5 en JavaScript
1/2 //devuelve 0 en Java

Además de estos, JavaScript proporciona los operadores aritméticos que constan en la siguiente lista.

%(Módulo)     Operador binario. Devuelve el resto de la división entera entre sus dos operandos.     12 % 5 devuelve 2.

++ (Incremento)     Operador unitario. Suma uno a su operando. Si se usa como prefijo (++x), devuelve el valor de su operando después de la suma; si se usa como sufijo (x++), devuelve el valor de su operando antes de sumarle uno.     Si x es 3, entonces ++x establece x a 4 y devuelve 4, mientras que x++ establece x a 4 y devuelve 3.

–(Decremento)     Operador unitario. Resta uno a su operando. Su funcionamiento es análogo al del operador de incremento.     Si x es 3, entonces –x establece x a 2 y devuelve 2, mientras que x– establece x a 2 y devuelve 3.

-(Cambio de signo)     Operador unitario. Devuelve su operando cambiado de signo.     Si x es 3, entonces -x devuelve -3.

Operadores lógicos:

Los operadores lógicos son generalmente empleados con valores lógicos (booleanos); estos operadores devuelven un valor booleano. Sin embargo, los operadores && y || realmente devuelven el valor de uno de sus operandos, por esto si se emplean con valores no booleanos, podrían devolver un valor no booleano. Los operadores lógicos se describen en la siguiente tabla.
&&     expr1 && expr2     (AND lógico) Devuelve expr1 si la expresión puede convertirse a falso; de otro modo, devuelve expr2. Cuando se emplea con valores booleanos, && devuelve true cuando ambos operandos son verdaderos; si no, devuelve false.

||     expr1 || expr2     (OR lógico) Devuelve expr1 si puede convertirse a verdadero; de otro modo devuelve expr2. Cuando se emplea con valores booleanos, el operador || devuelve true si alguno de los operandos es verdadero; si ambos operandos son falsos devuelve false.

!     !expr     (NOT lógico) Devuelve falso si su único operando puede convertirse a verdadero; de otro modo, devuelve verdadero.

Operadores de cadena de caracteres (string)

Además de los operadores de comparación, los cuales pueden ser empleados con los valores de cadena, el operador de concatenación (+) concatena dos valores de cadenas juntos, retornando otra cadena que es la unión de los dos operandos de tipo cadena. Por ejemplo, “mi ” + “cadena” retorna la cadena “mi cadena”.

El operador abreviado de asignación += también puede usarse para concatenar cadenas. Por ejemplo, si la variable micadena tiene el valor “alfa”, la expresión micadena += “beto” se evalúa como “alfabeto” y asigna este valor a micadena.

Excepciones:

Sentencia try…catch

La sentencia try…catch marca un bloque de las instrucciones a probar y especifica una o más respuestas al producirse una excepción. La sentencia try…catch es la que se ocupa de la excepción.

La sentencia try…catch consiste de un bloque try, el cual contiene una o más sentencias y cero o más bloques catch, conteniendo sentencias que especifican que hacer si una excepción es lanzada en el bloque a probar [try block]. Esto es, si desea que el bloque try suceda y si este no sucede, desea controlar el paso al bloque catch. Si cualquier sentencia dentro de un bloque try (o en una función llamada dentro de el bloque try) lanza una excepción, el control immediatamente cambia al bloque catch. Si no sucede el lanzamiento de ninguna excepción en el bloque try, el bloque catch es saltado. El bloque finally se ejecuta después de los bloques try y los bloques catch se ejecutan pero antes de las sentecias seguidas de la sentencia try…catch.

El ejemplo siguiente utiliza una sentencia try…catch. El ejemplo invoca una función que recupera un nombre de mes desde un arreglo basado en los valores pasados a la función. Sí el valor no corresponde a un número de mes (1-12), una excepción es lanzada con el valor Número_mes_Inválido y las sentencias en el bloque catch configuran la variable Nombremes a desconocido [unknown].

function encuentraNombredelMes (mes) {
    var mes = mes-1; // Ajusta el número del mes por el índice de lista
                     // (1=Enero, 12=Diciembre)
    var meses = ["Enero","Febrero","Marzo","Abril","Mayo","Junio",
                "Julio", "Agosto","Septiembre","Octubre",
                "Noviembre","Diciembre"];
    if (meses[mes] != null) {
        return meses[mes]
    } else {
        throw "Número_mes_Inválido" // se genera un objeto de
                                    // tipo Error
    }
}
try {
    // instrucciones a probar
    var nombremes = encuentraNombredelMes (miMes) // función que podría
                                                  //lanzar una excepción
} catch (e) {
    Nombremes ="desconocido"
    logMisErrores(e) // pasa el objeto excepción al manejador de errores
}

Throw acepta una expression que especifica el valor de la excepcion. Por ejemplo:

– throw “Error2”; // Genera una excepcion con un valor string
– throw 42; // Genera una excepcion con un valor numerico 42 (puede ser usada para manejar los errores por codigo)
– throw true; // Genera una excepcion con el valor true

El bloque finally

El bloque finally contiene sentencias para ejecutar después de que se ejecuten los bloques [try y catch] pero antes de las sentencias seguidas de la sentencia try…catch. El bloque finally se ejecuta sin importar que una excepción sea lanzada o no. Si una excepción es lanzada, las sentencias en el bloque finally se ejecutan aún si los manejadores de bloques no capturan la excepción.

Puede utilizar el bloque finally para hacer que su script falle graciosamente cuando ocurra una excepción, por ejemplo, puede necesitar liberar un recurso que su script lo tiene reservado. El siguiente ejemplo abre un archivo y luego ejecuta sentencias que utilizan el archvo (del lado del servidor JavaScript le permite acceder a archivos). Si una excepción es lanzada mientras el archivo es abierto, el bloque finally cierra el archivo antes de que el script falle.

abrirMiArchivo();
try {
    escribirMiArchivo(losDatos); // Aqui podria generarse un Error
} catch(e){
    handleError(e); // Si se tiene un error lo manipulamos
} finally {
    cierreMiArchivo(); // siempre cierra el recurso
}

Sobre el “Objeto Global”

En JavaScript todas las funciones, y variables deben pertenecer a algun objeto, por tanto para las que son globales en realidad pertenecen a al “Objeto Global” que sorprendetemente no tiene un nombre especifico, es posible a veces obtener una referencia a el mediante “this”, pero no siempre. En los browser web, el objeto “window” y “self” son miembros del “Objeto Global”.

Cuando se hace referencia a una variable en JavaScript, esta es buscada en el contexto local, sino se encuentra, entonces se busca en el “Objeto Global”, y sino se encuentra, se genera un Error.

La especificación ECMAScript no habla de la posibilidad  de tener multiples “Objeto Global”, sin embargo los browser soportan esto, cada window tiene su “Objeto Global”.

Sobre el punto-y-coma:

Uno de los objetos del lenguaje es que es posible omitir el punto-y-coma como terminador de una sentencia, por tanto pueden encontrar implementaciones del lenguaje que lo requieran o no, de cualquier forma la recomendación es usarlo siempre.

Palabras reservadas del lenguaje:

abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function
goto
if implements import in instanceof int interface
long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with

Cualquiera de estas palabras no puede ser usada como:
1. Nombre de un objeto literal
2. Miembro en notación “.” (Error del lenguaje que si es posible usarlo mediante “[]”)
3. Argumento de una funcion
4. Variable (var)
5. Variable global (variable sin var)

Conclusiones:

JavaScript es un lenguaje sencillo pero poderosamente expresivo, hemos visto una introducción básica a la sintaxis del lenguaje, en proximos post veremos como JavaScript implementa la programación orientada a objetos y los tipos de herencia que existen, o sea iremos produndizando en el lenguaje, no se alejen que esto se pone cada vez mejor.

Referencias:

http://javascript.crockford.com/survey.html

http://developer.mozilla.org/en/docs/About_JavaScript

Un comentario en “JavaScript: Introducción básica a su sintaxis.

Agregar un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *