Review: Professional JavaScript for Web Developers, Capítulo 5 (Parte II)
El tipo RegExp
ECMAScript soporta expresiones regulares a través del tipo RegExp. No voy a entrar mucho en detalle sobre las expresiones regulares pero son muy parecidas a las expresiones regulares de PERL.
Podemos crear una experesión regular utilizando el constructor RegExp o la siguiente sintaxis:
var expresion = new RegExp("patron", "banderas");
var expresion = /patrón/banderas
Las banderas (flags) indican de que forma se ejecutará la expresión regular. Hay tres modos:
- g: Indica el modo global, significa que se buscarán coincidencias con el patrón en toda la cadena y no parará después de encontrar la primera coincidencia.
- i: Indica modo case-insensitive. No se tiene en cuenta las diferencias entre mayúsculas y minúsculas.
- m: Indica el modo multilinea. Significa que el patrón seguirá buscándose en textos multilineas, aunque llegue al final de una línea.
Para el patrón existen un conjunto de carácteres ( [ { \ ^ $ | ) ? * + . que tienen un significado especial; por ejemplo el carácter ^ significa al principio por lo que la siguiente expresión regular /^a/ coincidiría con todas las cadenas que tengan una a al principio. El autor no explica el significado de cada carácter especial pero significa lo mismo que en las expresiones regulares de PERL.
Para ejecutar la expresión regular sobre una cadena basta con invocar al método exec sobre el patrón; nos devolverá un array con todas las coincidencias que haya encontrado:
var patron = /^a/g; var texto = "abcde"; var coincidencias = patron.exec(texto);
Si lo que queremos es saber si una cadena pasa una determinada expresión regular podemos utilizar el método test() que devuelve true si hay al menos una coincidencia y false en caso contrario.
if(patron.test(texto)){
alert("El patrón coincide");
}
El tipo Function
Las funciones actúan como objetos. Cada función que definimos es una instancia del tipo Function. Tenemos varias forma de definir una función:
function sumar(num1, num2){
return num1+num2;
}
var sumar = function(num1, num2){
return num1+num2;
};
De la segunda forma no hay nombre incluido despues de la palabra clave function, ya que la función puede ser referenciada a través de la variable sumar. También hay que fijarse que en el segundo caso hay un punto y coma ya que se trata de una inicialización de una variable.
Existe otra forma de definir una función utilizando el constructor Function pero no se recomienda por ser menos legible y tener menos rendimiento.
Lo importante de todo esto es tener claro que las funciones son objetos, por lo que el nombre de una función no es más que un puntero al objeto Function. De esta forma podemos copiar funciones en otras variables como haciamos con los objetos:
var hola = function(){
return "Hola";
}
hola(); //devuelve "Hola"
var otroSaludo = hola;
otroSaludo(); //Devuelve "Hola";
Importante es notar que utilizamos el nombre de la variable solamente, ya que si utilizaramos los paréntesis estaríamos invocando la función y asignando a la variable otraFuncion el resultado “Hola” y no el puntero al objeto Function.
Ahora podemos entender mejor porque no existe la sobrecarga de funciones en JavaScript. Ya que los nombres son punteros al objeto Function, estaríamos sobreescribiendo el valor al definirla dos veces con el mismo nombre, por lo que la función válida sería la última en definirse.
Dado que las funciones son objetos, podemos utilizar las funciones como parámetros de una función, e incluso devolver una función como resultado de otra función:
function unaFunction(otraFuncion, argumento){
return otraFuncion(argumento);
}
function devolverFuncion(){
return function(){
alert("Hola");
};
}
var dameFuncion = devolverFuncion(); //en dameFuncion tenemos un objeto Function
dameFuncion(); //"Hola"
Todas las funciones tienen dos objetos especiales, arguments y this. El autor ya habló de arguments en capítulos anteriores pero no había nombrado que el objeto arguments posee una propiedad llamada callee que es un puntero a la función que contiene el propio objeto arguments:
function numero(num){
alert(num);
if(num == 0){
return 0;
} else {
return arguments.callee(num-1);
}
}
El otro objeto especial es this que es una referencia al objeto donde la función está operando – o mejor dicho, el ámbito en el cual la función ha sido ejecutada. Cuando definimos una función en el ámbito global, el objeto this apunta a window.
window.nombre = "Fran";
var objeto = {
nombre: "Jose"
};
function saludar(){
alert(this.nombre);
}
saludar(); //"Fran" dado que la función se ha definido en el contexto global, this apunta a window.
window.saludar(); //Es exactamente lo mismo que lo anterior, dado que todo lo que definimos en el contexto global pertenece al objeto window
objeto.saludar = saludar; //Asignamos la función saludar al objeto
objeto.saludar(); //"Pepe" dado que ahora la función apunta al objeto que la invoca
La función global saludar() y la función del objeto apuntan al mismo objeto Function, pero se ejecutan en contextos diferentes. De ahí deducimos que el valor de this no se sabe hasta que la función se invoca y se determina el contexto de ejecución donde se está invocando.
Como las funciones son objetos tienen propiedades y métodos. Cada función tiene dos propiedades, length que indica el número de argumentos de la definición de la función, y prototype, la parte más interesante del núcleo de ECMAScript. La propiedad prototype indica la localización actual de todos los métodos de instancia para los tipos de referencia; esto significa que métodos como toString() y valueOf() existen en el prototipo y son accedidas desde todas las instancias de un objeto. Esta propiedad es muy importante y la explicará mejor en el siguiente capítulo.
También cuentan con dos funciones, apply() y call(). Estos métodos llaman a la función dentro de un ámbito.
El método apply() acepta dos argumentos, el ámbito en el que se ejecutará la función, y un array de argumentos.
El método call() tiene el mismo objetivo, pero se invocan de manera diferente, el primer argumento indica el ámbito en el que se ejecutará la función, los siguientes argumentos serán los argumentos con los que se invoque la función.
Con estas dos funciones podemos aumentar el ámbito en el que la función se ejecutará:
window.nombre = "Fran";
var objeto = {
nombre : "Jose"
};
function saludar(){
alert(this.nombre);
}
saludar.call(this); //"Fran", dado que el objeto this apunta al objeto global window
saludar.call(window); //"Fran", dado que el objeto this apunta a window
saludar.call(objeto); //"Jose", dado que se ejecuta en el ámbito del objeto
Wrappers de tipo primitivo
En ECMAScript existen wrappers (envoltorios) de los tipos primitivos String, Number y Boolean. Podemos crear nuevas instancias a través del operador new:
var booleano = new Boolean(false);
var numero = new Number(23);
var cadena = new String("Fran");
Pero hay que tener ciertos aspectos en cuenta. Por ejemplo:
if(new Boolean(false)){
alert("Entra dentro del if");
}
Esto es así, porque si recordamos, cualquier objeto que no sea null se transforma en un booleano true a través de la función casting Boolean (coerción de tipos), incluso aunque sea un objeto de tipo Boolean con valor false.
Los objetos de tipo referencia que envuelven a los valores primitivos cuentan con una serie de métodos que podemos utilizar. De entro los más interesantes podemos destacar todo lo relevante a la manipulación de cadenas y números.
Objetos preconstruidos
Por último, tenemos los objetos preconstruidos Math y Global.
El objeto Global es un atajo para métodos y propiedades. Todo lo que definimos globalmente se convierten en propiedades del objeto Global; funciones como isNaN(), isFinite(), parseInt(), parseFloat() pertenecen al objeto Global. También pertenecen otros métodos como encodeURI() y encondeURIComponent(), utilizados para codificar URIs; decodeURI() y decodeURIComponent() para decodificar URIs, eval() para interpretar y ejecutar código.
La mayoría de navegadores implementan todo esto como parte del objeto window. Todas las variables y funciones declaradas en el ámbito global forman parte como propiedades del objeto window.
El objeto Math se utiliza para ejecutar operaciones matemáticas y es muy similar al objeto Math de otros lenguajes como Java.
Por donde y hacia donde vamos
De momento llevamos cinco capítulos resumidos (unas 200 páginas del libro), donde hemos visto muchas características importantes del lenguaje. Estudiando estos capítulos he entendido perfectamente la importancia de los contextos de ejecución, del valor que toma el objeto this dentro de las funciones, y como utilizar apply y call para invocar funciones dentro de un ámbito. El siguiente capítulo está dedicado a la orientación a objetos en JavaScript, como instanciar objetos, herencia, prototipos, etc. La verdad es que estudiar así un libro es mucho mejor, resumirlo después de leerse cada capítulo ayuda a aclarar las ideas y a entender profundamente el lenguaje. Sobretodo probando ejemplos en el navegador e intentando jugar un poco con ellos. Voy un poco más lento de lo que me gustaría, dado que quiero leerme muchos libros en lo que me queda de año, pero creo que es mejor leerlos en profundidad a darles una pasada.
Fantastic items from you, man. I have consider your stuff prior to and you’re just too wonderful. I really like what you’ve acquired here, certainly like what you’re saying and the way wherein you say it. You make it entertaining and you still take care of to stay it smart. I cant wait to learn much more from you. This is really a terrific website.
Affair, personalised wine labels for your next celebration or function.
8 minutes ago via Echofon Reply Retweet Favorite powered by socialditto thesulkAlec
SulkinWhite wine is just I’m disappointed in my husband
juice, right?