Hace tiempo que javascript me tiene enamorado y poco a poco voy descubriendo nuevas propiedades y nuevas técnicas de programación que no podríamos tener en otros lenguajes.
Una curiosidad de javascript es la de poder igualar variables a funciones:
function nombre(){ alert("Hola"); }
//
var variable = nombre();
// -> Muestra un alert()
console.log(variable.toString());
// TypeError: variable is undefined
// igualamos
var foo = nombre;
console.log(foo.toString());
//function nombre() { alert("Hola"); }
Como vemos en el ejemplo anterior, si deseamos igualar una variable a una función deberemos hacer sin añadir los paréntesis que se añaden habitualmente a las funciones, añadir los paréntesis implica la ejecución de la función. De esta forma, podemos aprovecharnos de dicha propiedad para hacer cosas interesantes:
var $$$ = function(){
if (document.getElementsByClassName){
return function(klass){
return document.getElementsByClassName(klass);
}
} else {
return function(klass){
var result = new Array();
var reg = new RegExp( "(?:^|\\s)" + klass.replace( /\./g, "\\s*" ) + "(?:\\s|$)" );
var es = (document.all) ? document.all : document.getElementsByTagName("*");
for( var index = 0, e; e = es[ index++ ]; ) {
if( reg.test( e.className ) ) {
result[ result.length ] = e;
}
}
return result;
}
}
}()
Este ejemplo nos sirve para ilustrar lo que intento explicar en este artículo. Si nos fijamos en el código, está condicionado por la existencia del método getElementsByClassName
del objeto document
, en caso de existir devolvemos una función que la usa para obtener los elementos con la clase solicitada.
En caso de no existir dicho método, se encarga de devolver una funcionalidad desarrollada usando getElementsByTagName
con la que obtenemos el mismo resultado pero en navegadores donde getElementsByClassName
no está disponible.
Al final del código (y en negrita) vemos los famosos paréntesis de los que hemos hablado antes. En este caso, ejecutará dicho código una vez pase por él, dejándonos la variable $$$
cargada con el método que más le convenga dependiendo de la existencia del método getElementsByClassName
.
Hagamos unas pruebas 😀
var $$$ = function(){
if (document.getElementsByClassName){
return function(klass){
return document.getElementsByClassName(klass);
}
} else {
return function(klass){
var result = new Array();
var reg = new RegExp( "(?:^|\\s)" + klass.replace( /\./g, "\\s*" ) + "(?:\\s|$)" );
var es = (document.all) ? document.all : document.getElementsByTagName("*");
for( var index = 0, e; e = es[ index++ ]; ) {
if( reg.test( e.className ) ) {
result[ result.length ] = e;
}
}
return result;
}
}
}()
// Con getElementsByClassName
$$$.toString()
// --> "function (klass) { return document.getElementsByClassName(klass); }"
$$$("framework")
// --> [th.framework, th.framework, th.framework, th.framework, th.framework, th.framework]
//Sin getElementsByClassName
$$$.toString()
// --> "function (klass) { var result = new Array; var reg = new RegExp("(?:^|\\s)" + klass.replace(/\./g, "\\s*") + "(?:\\s|$)"); var es = document.all ? document.all : document.getElementsByTagName("*"); for (var index = 0, e; e = es[index++];) { if (reg.test(e.className)) { result[result.length] = e; } } return result; }"
$$$("framework")
// --> [th.framework, th.framework, th.framework, th.framework, th.framework, th.framework]
Ventajas
Al ser ejecutado al cargar el script tenemos una ventaja a la hora de ejecutar dicho método, no tendremos que realizar una comprobación de la función para elegir un camino u otro, la función ya estará cargada con el camino correcto que debe usar, en el caso del elemento el getElementsByClassName
.
Desventajas
Perdemos unas milésimas de segundo en la carga del fichero, esto es debido a que ha de compilar el código y ejecutar la función, en este caso el tiempo no es significativo, pero en scripts más pesados y/o complejos puede llegar a notarse dicho tiempo, dependiendo el uso de la funcionalidad nos puede ser interesante usarlo o no.
¿Alguien sabe que nombre recibe esta técnica? Llevo tiempo usándola, pero nunca he sabido el nombre que recibe.
Actualización
Me he olvidado de algo que podría ser interesante. Resulta que además de esta funcionalidad, disponemos de la posibilidad de pasar una variable a la función y usarla dentro de la función que estamos auto generando.
var foo = true; // o false;
var func = function(bla){
if (bla){
return function(str){
console.log("USAMOS CONSOLE: " + str);
}
} else {
return function(str){
alert("USAMOS ALERT: " +str);
}
}
}(foo)
En el ejemplo nos encontramos la declaración de la función que recibe un parámetro llamado bla
, parámetro que pasamos en la última línea, entre los parámetros usando la variable foo
. Dentro podremos usar bla
que es el parámetro que estamos recibiendo dentro. Una curiosa forma de auto programar nuestras aplicaciones 😀
14 comentarios, 2 referencias
+
#