¿Que es lo que hace: jQuery.noConflict()?


De vez en cuando me gusta leer el código de alguna buena librería para descubrir cosas interesantes. El código de jQuery es de esos que contiene un buen número de detalles de los que se puede aprender bastante. Es un código atractivo y más sencillo de seguir de lo que podría imaginarse.
Hoy, tras una conversación reciente, me quiero centrar en la implementación de la función noConflict()

El problema

Ya desde su versión 1.0, John Resig -creador de jQuery- tuvo muy clara una idea en la arquitectura de la librería: Causar la mínima polución de nombres posible. ¿Por qué? Por aquel entonces, la librería más popular -PrototypeJS- había seguido el camino de crear las funciones globales que creyó necesarias y de añadir propiedades y métodos a los objetos nativos de Javascript. Entre esas funciones globales, lo que más llamaba la atención era el uso de alias como $$H o $F$ es un nombre muy corto que enseguida se hizo popular. Claro, otras librerías decidieron usar ese mismo alias. Luego, cuando los desarrolladores-usuarios querían incluir en su página un determinado elemento hecho con una librería y otro hecho con otra distinta... Colisión de nombres y problemas sin fin.
Pero claro, por otra parte el alias $ es realmente apetecible por su comodidad. Así que en jQuery, buscando dar a sus usuarios la mayor flexibilidad posible para utilizar su librería junto a otras, se decidió usar el alias pero a la vez proporcionar un medio de liberar ese alias, la función noConflict().

Uso de noConflict()

El uso de noConflict() es sencillo. Cargamos jQuery, lo que define el alias $. Luego usamos noConflict() y eso libera el alias, dejando disponible el que hubiera antes en caso de que lo hubiera.
No hay mucho más que decir, más que nada porque ya está dicho en muchos sitios. Incluso en la propia documentaciónoficial de jQuery.

Pero, ¿cómo funciona?

En realidad es bastante sencillo. Todo se basa en el estricto seguimiento por parte de los desarrolladores del principio de encapsulación de alcance. Veámoslo directamente sobre el código. Lo que sigue es el código de jQuery 1.4.4. pero sólo las partes implicadas, claro:
(function( window, undefined ) {

    // Use the correct document accordingly with window argument (sandbox)
    var document = window.document;
    var jQuery = (function() {
        // Define a local copy of jQuery
        var jQuery = function( selector, context ) {
            // The jQuery object is actually just the init constructor 'enhanced'
            return new jQuery.fn.init( selector, context );
        }

        // Map over jQuery in case of overwrite
        _jQuery = window.jQuery
        // Map over the $ in case of overwrite
        _$ = window.$

        jQuery.fn = jQuery.prototype = {
            // The current version of jQuery being used
            jquery: "1.4.4"
        };
        jQuery.extend = jQuery.fn.extend = function() {
            // ...
        };

        jQuery.extend({
            noConflict: function( deep ) {
                window.$ = _$;
                if ( deep ) {
                    window.jQuery = _jQuery;
                }
                return jQuery;
            }
        });
        // Expose jQuery to the global object
        return (window.jQuery = window.$ = jQuery);
    })();
})(window);
Lo primero es que todo el código de la librería está contenido dentro de una función anónima a la que se llama de forma inmediata, recibiendo los valores de window y de undefined. Con esto lo que se logra es que, si seguimos la recomendable práctica de declarar nuestras variables localmente en el entorno que corresponde (usando var) evitaremos causar cualquier conflicto en el alcance global del intérprete. El recibir undefined se hace con un objetivo simétrico: evitar recibir valores de undefined que vengan alterados por otros scripts. window se recibe para obtener una referencia local (más rápido) y localizar la referencia al entorno global en 1 único sitio ( ver explicación en el comentario más abajo )
Una vez nos encontramos en ese entorno, se declara una variable llamada jQuery. Es importante notar que esta variable es local, vive únicamente dentro de este alcance. Y no va a salir de ahí. Definimos ahí un nuevo alcance y dentro de él es donde se va a desarrollar todo el contenido de jQuery. De hecho, es en ese nuevo alcance donde se define otrajQuery local y sobre ella se trabaja, añadiéndole todas las funciones que usamos habitualmente.
En ese mismo alcance donde está definiendo jQuery, se da el primer paso necesario para el funcionamiento denoConflict(): Se captura el (posible) valor existente de $. Fijémonos porque es interesante:
// Map over the $ in case of overwrite
_$ = window.$
Para acceder al $ global, lo hacemos explícitamente a través de window. Ah, y lo mismo se hace con el propio nombrejQuery. Bien, ambos valores se guardan creando sobre ellos una closure. Ahí estarán disponibles para cuando los necesitemos.
Tras crear todas las funciones y objetos necesarios, la forma de hacer disponibles tanto jQuery como $ en el alcance global, no es simplemente devolver los objetos in más, sino que se exponen explícitamente sobre el objeto window:
return (window.jQuery = window.$ = jQuery);
Ahora, después de haber cargado y construido jQuery, es cuando podemos llamar a noConflict(). ¿Qué es lo que ocurre cuando lo hacemos? Sencillo:
            noConflict: function( deep ) {
                window.$ = _$;
                if ( deep ) {
                    window.jQuery = _jQuery;
                }
                return jQuery;
            }
Por una parte, volvemos a exponer como window.$ el objeto que habíamos capturado inicialmente en _$. Si lo pedimos, se hace también lo mismo con el nombre jQuery. La liberación de $ es interesante para cualquier librería que lo use, la de jQuery permite la convivencia con otras versiones de la propia librería. Además, por si el usuario lo prefiere devolvemos también el objeto jQuery.

Ejemplo

Si vemos el siguiente ejemplo:
<!DOCTYPE HTML >
<html>
<head>
<title>Muchas jQueries!</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" ></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js" ></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" ></script>
<script type="text/javascript">
    var jqs = {};
    jqs.jq144 = jQuery.noConflict(true);
    jqs.jq143 = jQuery.noConflict(true);
    jqs.jq142 = jQuery.noConflict(true);
    jqs.jq141 = jQuery.noConflict(true);

    jqs.jq144(function($) {
        $("#out").html("141: " + jqs.jq141().jquery + "<br/>142: " + jqs.jq142().jquery +"<br/>143: " + jqs.jq143().jquery +"<br/>144: " + jqs.jq144().jquery );
    });
</script>
</head>
<body>
<div id="out"></div>
</body>
</html>
Tras haber cargado las 4 versiones de jQuery, lo que tenemos es algo como esto:
jQuery {
    version 1.4.4
    closure ( _jQuery = jQuery {
        version 1.4.3
        closure ( _jQuery = jQuery {
            version 1.4.2
            closure ( _jQuery = jQuery {
                version 1.4.1
            })
        })
    })
}
Con la primera llamada a jQuery.noConflict() lo que hacemos es devolver el actual jQuery y asignar el anterior (_jQuery) a window.jQuery. Así queda nuestra estructura:
    jQuery {
        version 1.4.3
        closure ( _jQuery = jQuery {
            version 1.4.2
            closure ( _jQuery = jQuery {
                version 1.4.1
            })
        })
    }
Algo similar se va haciendo con $. Cuando llamamos por segunda vez... Realmente estamos llamando alnoConflict() del objeto que está ahora en jQuery, que es la versión 1.4.3. Es decir, no es -aunque lo parezca- la misma llamada que antes. Se llama igual, pero es una función de otro objeto.

Conclusiones

jQuery utiliza una estructura muy definida para evitar por todos los medios crear conflictos de colisiones con otras librerías o incluso con otras versiones de ella misma. Además, proporciona la función noConflict() como herramienta fundamental para solucionar esas colisiones.

Diferencias entre null y undefined


En javascript existen cinco tipos primitivos de datos: undefined, null, boolean, number y string.
A primera vista no se aprecia la diferencia entre los tipos undefined y null.
El tipo undefined corresponde a las variables que han sido definidas y todavía no se les ha asignado un valor.
El tipo null se suele utilizar para representar objetos que en ese momento no existen.
Sin embargo aunque son conceptos distintos el operando de igualdad los considera iguales. No así el operando typeof o el operador de igualdad estricta ===
(undefined == null) //--> true
(undefined === null) //--> false
(typeof undefined == typeof undefined null) //--> false
Si intentamos operar con una variable que tiene valor null, según el contexto devolverá los siguientes resultados.
Boolean: false
Numeric: 0
String: null
Si intentamos operar con una variable que tiene valor undefined, según el contexto devolverá los siguientes resultados.
Boolean: false
Numeric: NaN
String: undefined

Recomendación SQLera

Bueno mis estimados lectores el día de hoy les comento sobre un libro que esta muy interesante, y que esta enfocado en ayudar a dar ese paso a los desarrolladores de ASP.Net 2.0 hacia el 4.0, su temática es sencilla, ponernos en contexto sobre que es la tecnología de lado de servidor, su evolución... protagonismo el scripting por lado del cliente, y como aprovechar al máximo las bondades de ambas, tecnologías.

Este libro y el autor José Manuel Alarcón Aguín, nos llevan de la mano, en sus capítulos, si bien se parte desde 0 en la explicación de las tecnologías, es necesario tener conocimiento básico o intermedio de ASP.Net, Javascript y html.


los temas tratados los capitulo son los siguientes:

  • Las diferentes versiones de ASP.NET y qué ofrecen al programador
  • Fundamentos de AJAX. Con cualquier tecnología, no atado a ASP.NET.
  • ASP.NET AJAX en el lado servidor.
  • ASP.NET AJAX en el lado cliente y el modelo de desarrollo “puro” con AJAX
  • Enlazado a datos en el lado cliente. La tecnología de Live Binding es la principal novedad de ASP.NET 4.0. Este es el primer libro del mercado en el que se trata esta nueva funcionalidad.
  • Generación automática de interfaces de “mantenimiento” con Dynamic Data.
  • Filtrado automático de datos con Query Extenders. Otra novedad de ASP.NET 4.0 sobre la que no verás escrito en ningún otro lado.
En resumen lo que podemos aprender del libro y sus tips es:
  •  asp.net y sus versiones
  • fundamentos de ajax
  • asp.net ajax en el navegador
  • asp.net ajax en el servidor
  • optimización y uso de bibliotecas
  • asp.net dynamic data interfaces de datos adaptables
  • filtrado de datos automatico con query extender
muy buen libro y altamente recomendado si te llama la atención en desarrollo web y la plataforma .net. Les dejo el link del libro en linea para que si es de su agrado le den un vistazo.


Saludos!

Enviar correo electrónico en un formato tabular utilizando el correo electrónico de la base datos SQL Server

Enviar correo electrónico en un formato HTML utilizando el correo electrónico de la base datos SQL Server

101 citas célebres del mundo de la informática

Después de pasar un buen rato entretenido con la recopilación de frases célebres relacionadas con el mundo de la informática y especialmente el desarrollo de software, "101 Great computer programming quotes", publicado en DevTopics hace unas semanas

Tips para ser un mejor programador

1. Estudia, estudia y estudia
El estudiar nos permite perfeccionarnos, cuanto mas estudiemos mas oportunidades de programar mejor tendremos, no solamente estoy hablando de universidades, ni tampoco de cursos, hoy por hoy gracias a internet existen

LINQ: Consulta Maestro-Detalle

Problema


Lo primero, voy a exponer el problema que me han planteado:
Dada una tabla, digamos, “Cabecera”, con una tabla relacionada de “Detalle” con una relación 1 a

Diez Años de .Net

En el boletín de Microsoft del MSDN Flash que recibí este día dice que ya son 10 años de .Net y justamente recuerdo cuando inicie mis días de programación con .Net.


En aquella época estaba la versión 2002 de Visual Studio

Más allá de las bases de datos relacionales

supernova

Las bases de datos relacionales, como MySQLPostgreSQL y varios productos comerciales, nos han servido bien durante muchos años. Últimamente, sin embargo, ha habido mucha discusión sobre si el modelo relacional está llegando al final

Cannot resolve the collation conflict between "Modern_Spanish_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.

El día de hoy estaba trabajando con unas tablas de unas bases de datos del servidor en donde trabajo... y al realizar una consulta, me arrojaba un error sobre su COLLATION (intercambio de caracteres entre columnas). Un error así...:

Cannot resolve the collation conflict between "Modern_Spanish_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.

Diez errores comunes de CSS

Recientemente he estado modificando el código en un sitio web diseñado por alguien más, cuando vi a varios errores comunes en la hoja de estilos. Pensé que sería útil