en Javascript, jQuery

Cómo extender objetos con jQuery. Diferencia entre $.extend y $.fn.extend

En muchos de los plugins de jQuery que manejamos vemos las expresiones $.extend (o jQuery.extend) y $.fn.extend (o jQuery.fn.extend).

Pues bien, lo que estamos viendo en estas expresiones es la aplicación del metodo .extend().

Este método es la base para la creación de plugins y para la parametrización de nuestros plugins (es decir poder tener unos valores por defecto que el usuario pueda modificar al llamar al plugin).

Pero… ¿que hace exactamente el metodo .extend()?

Basicamente lo que hace es extender objetos. Esto significa que, dado un objeto, le añade el contenido (funciones y variables) de otro objeto (o de otros).

La nomenclatura de este metodo es la siguiente:


    jQuery.extend( target, [ object1 ], [ objectN ] )

Ahora bien, dependiendo del numero de objetos que reciba, el resultado final será diferente…

Cuando .extend() recibe un unico objeto

En este caso, como solo se le pasa un objeto, lo que hace es añadir los metodos definidos en este objeto al objeto jQuery o al objeto jQuery.fn (tambien llamado jQuery.prototype o $.fn)

Como norma general, debemos extender el objeto jQuery para funciones, y el objeto jQuery.fn para metodos. Una funcion, a diferencia de un metodo, no puede ser accedida directamente desde el DOM.

Por ejemplo, si extendemos el objeto jQuery.fn de esta forma:


    $.fn.extend({
             myMethod: function(){...}
 });

Podremos aplicar este nuevo metodo a elementos del DOM de esta forma:


    $("div").myMethod();
      // aunque tambien podria llamar asi: $.fn.myMethod();

Y si extendemos el objeto jQuery de esta forma:


    $.extend({
                myMethod2: function(){...}
        });

Podremos llamar a esta nueva funcion de esta forma


    $.myMethod2();

Cuando .extend() recibe dos o más objetos

Aquí lo que hace es añadirle al primer objeto, los metodos y variables definidos en el resto de objetos.

Por ejemplo:


    defaults = { size: 3 };
   options = { height: 6 };
  var opts = $.extend(defaults, options)

      // \'defaults\' recibe los metodos y variable definidos en \'options\'
        // opts == defaults == { size: 3, height: 6 }
     // options == { height: 6 };

El objeto defaults se amplia (se extiende) con los elementos del objeto options. El objeto options permanece igual.

Si el primer objeto está vacio, se añadirán los metodos y variables del resto de objetos en un nuevo objeto. Esto es util cuando queremos agrupar los metodos y variables de diferentes objetos sin modificar ninguno de ellos.

Por ejemplo:


    var  opts = $.extend( {}, defaults, options)

        // \'opts\' recibe todos los metodos y variables definidos en \'defaults\' y  \'options\', sin que estos queden modificados
     // opts == { size: 3, height: 6 }
 // defaults == { size: 3 };
       // options == { height: 6 };

El objeto opts se amplia (se extiende) con los elementos de defaults y options. Los objetos defaults y options permanecen
igual.

Y por ultimo…. ¿hay más formas de extender los objetos jQuery, jQuery.fn o cualquier otro?

Pues si. Podemos extender cualquier objeto directamente con la nomenclatura de objetos, es decir haciendo …


    jQuery.myNewFunction_1 = function() {   
          // hago cosas chulas 
     }  

 jQuery.fn.myNewFunction_2 = function () {       
          // aquí tambien hago cosas chulas 
        }

   miObjeto.myNewFunction_3 = function () {        
          // y aquí no voy a ser menos 
     }

¿Y tú? ¿Has usado ya .extend() en tus aplicaciones? ¿Cómo lo has
aplicado? Cuentanos tu experiencia.

Enlaces y más

Post Anterior
Post Siguiente

Política de Comentarios de pixelovers

Responsable » Juan Manuel Garrido
Finalidad » Moderación de los comentarios
Legitimación » Tu consentimiento expreso que te será requerido por Disqus.
Destinatarios » Los datos de tus comentarios los guardará Disqus, mi sistema de comentarios, que está acogido al acuerdo de seguridad EU-US Privacy Shield tal y como recoge su politica de privacidad
Derechos » Desde Disqus, por tanto, podrás acceder, rectificar, limitar y suprimir tus comentarios o tu cuenta
Tienes más detalles acerca del tratamiento de los datos relacionados con los comentarios en nuestra (Política de Privacidad)

  1. Una entrada genial!! 😀

    Hasta ahora, no acababa de entender bien que hace el metodo extend(), y mucho menos las diferentes formas de aplicarlo, y que en cada caso, obtienes un resultado distinto.

    Mola mucho que se pueda extender la propia funcionalidad de jQuery mediante $.fn.extend({ … });

  2. hay una pequeña diferencia entre

    jQuery.myNewFunction_1=function();

    jQuery.prototype.myNewFunction=function();

    bueno eso en OOP en JS, aunque no se si se creen o no internamente nuevos objetos jQuery, es una pequeña diferencia en memoria…. todos los objetos en JS se pueden «prototipar» es decir que en base a este se puedan crear mas objetos, en si en JS no existen las clases como en Java, C++, C#, ya que estos generan los objetos a partir de un «molde» la clase, en JS es un leguaje basado en prototipos, se crea un objeto prototipo y a partir de este se copean los nuevos objetos, en si el termino correcto para referirnos a una «clase» es prototipo, podemos modificar un objeto y agregarle metodos o propiedades con tansolo decir..

    obj.nuevaPropiedad=»hola»;

    obj.nuevoMetodo=function(){}

    pero alli se modifica directamente el objeto.. un objeto comparte un prototipo con los objetos que son digamos «instancias» de este ultimo, para compartir el prototipo se accede a objeto.prototype todos los objetos en JS tienen un prototype, al modificar los el prototipo de un determinado Objeto todos los objetos de ese tipo se ven afectados en su estructura. mietras digamos tengo una funcion contructora (clases)

    var A=function(nombre){

     this.nombre=nombre;

     this.saludo=function(){

      alert(«hola «+nombre);

     }

    }

    de esta forma el metodo saludo se copea directamente al objeto y no al prototypo.. generandose una nueva funcion para cada uno de los objetos que se instacien a partir de «A»..

    mientras que si hiciera

    var A=function(nombre){

    this.nombre=nombre;

    }

    A.prototype=function saludo(){

    alert(«hola»);

    }

    A, «coparte» su prototypo con todas las instacias de «A»..con lo que no se vuelben a definir el metodo para cada una de las instacias de «A», esto reduce el consumo en memoria y los procesos en la creación de objetos. siempre es mejor modificar el prototype, amenos que expesificamente se quiera crear una funcion diferene para cada objeto y eso depende de lo que queremos lograr,

    ha y al acer obj.nuevaFuncion=function(), solo se le asigna a ese objeto esa nueva funcion mietras que si lo hacemos a prototype se asignan a todas las instacias del tipo..

    bueno espero averme explicado poquito de la diferencia de modificar directo un objeto o a su prototype.

    hasta ahorita no he usado ninguna de estas para JQuery en especifico pero si un monton de veces en mi programación avitual en JS

  3. @Ruben, gracias 🙂

    @Pakos, gracias por tu aportación.

    Estamos preparando un Post sobre Programacion Orientada a Objetos en Javascript donde abordaremos todo esto que comentas.

    En el blog de Andrés Nieto podemos encontrar un ejemplo donde se ve muy claro lo que comentas de añadir metodos a una «clase» mediante prototype.

  4. Juanma Garrido, de nada =).. y si exactamente eso es el efecto que se tiene al modificar un prototype una de tantas aplicaciones que se le puede dar, en el caso de jQuery, tal pareciera que esta fuera de tema pero no es así, ya que jQuery termina siendo un Objeto en JS… ;),

    nada mas comentario aqui ya que no lo pude dejar en el blog de Andrés Nieto, prototype no es un metodo como lo dice en su post, un pequeño error de termino tecnico, prototype es una propiedad que seria un apuntador al objeto comun (a la  base) de objeto en cuestion en su ejemplo refiere al objeto String (viendolo como objeto), un metodo es una accion, lo que en js seria una funcion de un objeto, solo eso de alli en mas creo que es un muy buen post, que ejemplifica lo que comentaba…