Ir al contenido principal

Cacheando objetos en jQuery


Artículo que me pareció  interesante para compartir que publicó Carlos Benitez en su blog.


Cuando utilizamos jQuery para la selección y manipulación de elementos del DOM, una práctica que a menudo olvidan los programadores es cachear los objetos.
Tomemos el siguiente código de ejemplo:
$('#myObjId').click(function() {
  if ( $('#myObjId').hasClass('clicked') ) {
    $('#myObjId').removeClass('clicked');
    $('#myObjId').css('background-color', 'red');
  } else {
    $('#myObjId').addClass('clicked');
    $('#myObjId').css('background-color', 'blue');
  }
);
$('#myObjId').val('Click Me!');
Con este fragmento comprobamos cómo cada vez que se realiza una acción, el selector interno de jQuery (Sizzle), debe recorrer el DOM completamente hasta encontrar el elemento sobre el que estamos operando, lo cual, dependiendo de la complejidad del sitio o de las acciones, puede suponer una reducción importante en el rendimiento.

Método clásico

Una forma de evitar ese coste es simplemente cacheando el objeto y luego operar directamente sobre su referencia, evitando así que jQuery tenga que buscarlo cada vez que lo necesitemos:
var $myObj = $('#myObjId');
$myObj.click( function(){
  if ( $myObj.hasClass('clicked') ){
    $myObj.removeClass('clicked');
    $myObj.css('background-color', 'red');
  } else {
    $myObj.addClass('clicked');
    $myObj.css('background-color', 'blue');
  }
});
$myObjId.val('Click Me!');
Al asignar una variable al selector, ésta referencia directamente al objeto jQuery, por lo que podemos operar sobre él con los métodos de la librería. Para recordar que se trata de un objeto jQuery, una buena práctica es añadir la ‘$’ delante del nombre de la variable.

Método mejorado

Todavía podemos mejorar el código anterior mediante el encadenado (chaining) de acciones sobre un mismo objeto:
var $myObj = $('#myObjId');
$myObj.click(function(){
  if ( $myObj.hasClass('clicked') ){
     $myObj.removeClass('clicked').css('background-color', 'red');
  } else {
    $myObj.addClass('clicked').css('background-color', 'blue');
  }
});
$myObjId.val('Click Me!');
De este modo, si tenemos que actuar sobre un mismo objeto con varias acciones consecutivas, no tendremos que recorrer el DOM una y otra vez ganando rendimiento.

Cacheando el objeto en funciones anónimas

Cuando aplicamos un callback a un evento, podemos cachear el objeto que lo recibe mendiante el comando this:
var $myObj = $('#myObjId');
$myObj.click( function(){
  var $this = $(this);
  if ( $this.hasClass('clicked') ){
    $this.removeClass('clicked').css('background-color', 'red');
  } else {
    $this.addClass('clicked').css('background-color', 'blue');
  }
} );
$myObjId.val('Click Me!');
De esta forma, no es necesario volver a buscar el objeto en el DOM con lo que de nuevo ahorramos recursos. De nuevo, para recordar que se trata de un objeto jQuery, es interesante utilizar un prefijo como ‘$‘.

Método Experto

Finalmente, es importante conocer el comportamiento interno de jQuery para optimizar al máximo nuestros selectores: cuando aplicamos una acción sobre un selector, jQuery nos devuelve de forma interna el propio objeto. Esto permite refactorizar el código anterior y mejorarlo:
var $myObj = $('#myObjId').click(function(){
  var $this = $(this);
  if ( $this.hasClass('clicked') ){
    $this.removeClass('clicked').css('background-color', 'red');
  } else {
    $this.addClass('clicked').css('background-color', 'blue');
  }
}).val('Click Me!');
En este caso, hemos realizado las operaciones sobre la misma declaración de la variable, seguros de que el objeto devuelto es siempre la referencia original. De este modo, aún conservamos la referencia al objeto jQuery para usarlo más adelante en nuestro código.

Comentarios

Entradas populares de este blog

Llenar un dropdownlist de mes con C#

Buenas, acá dejo un ejemplo de como llenar un dropdownlist. Lo publico como para tenerlo de referencia, tal vez a alguien le sirva también. Código en C# (code behind)        private void CargarMes()        {            //valor por default            ddlMes.Items.Add("Seleccione mes");            List<string> nombreMes = DateTimeFormatInfo.CurrentInfo.MonthNames.Take(12).ToList();            var listaMesesSeleccionados = nombreMes.Select(m => new            {                Id = nombreMes.IndexOf(m) + 1,                Name = m            });            foreach (var mes in listaMesesSeleccionados)            {  ...

Borrar carpetas .svn en Windows

Cuando se empieza a usar  Subversion  (SVN), para tener un control de los archivos de nuestro proyectos, en ocasiones usaremos clases, librerías, frameworks o carpetas de un repositorio de un tercero. Cuando unimos estas carpetas nuevas, a nuestro repositorio cliente, esta no los interpreta bien porque ya vienen con otras carpetas .SVN con archivos específicos para su repositorio de origen. La solución aquí es eliminar todas las carpetas .SVN de lo que queramos implementar para que nuestro repositorio cliente lo interprete como nuevos archivos y podamos agregarlas al proyecto. Con esto se eliminarán las carpetas .SVN de forma recursiva. Pero escribir toda esa línea no es muy cómodo que digamos en nuestro trabajo del día a día, por eso vamos a automatizar este proceso. En Windows Crearemos un archivo que llamaremos "borrar carpetas SVN.reg" y contendrá lo siguiente: Código : Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\shell\DeleteSVNFolders] ...

Recursividad

1.1.  Introducción . El concepto de recursividad va ligado al de repetición. Son recursivos aquellos algoritmos que, estando encapsulados dentro de una función, son llamados desde ella misma una y otra vez, en contraposición a los algoritmos iterativos, que hacen uso de bucles while, do-while, for, etc. 1.2.  Definición . Algo es recursivo si se define en términos de sí mismo (cuando para definirse hace mención a sí mismo). Para que una definición recursiva sea válida, la referencia a sí misma debe ser relativamente más sencilla que el caso considerado. 1.3. Elementos de la Recursión  1.3. 1.  Axioma  Es un caso donde el problema puede resolverse sin tener que hacer uso de una nueva llamada a sí mismo. Evita la continuación indefinida de las partes recursivas. 1.3.2.  Formula recursiva Relaciona el resultado del algoritmo con resultados de casos más simples. Se hacen nuevas llamadas a la función, pero están más próximas al caso base. Por eje...