2011-05-01 8 views
5

Tenía una pregunta sobre el patrón 'pato golpeando' que encontré por primera vez en el blog de Paul Irish. Tengo la premisa general ... guardar una referencia a una función existente, luego reemplazar la función existente con una rama condicional que llamará a una nueva función si se cumple la condición, o la versión anterior si no es así. Mi pregunta es por qué tenemos que usar "apply" con "this" como primer param cuando llamamos a la función _old? Entiendo cómo funciona aplicar, pero estoy buscando alguna aclaración sobre por qué es necesario.Observación del patrón Paul Irish 'pato perforación'

(function($){ 

     // store original reference to the method 
     var _old = $.fn.method; 

     $.fn.method = function(arg1,arg2){ 

      if (... condition ...) { 
       return .... 
      } else {   // do the default 
       return _old.apply(this,arguments); 
      } 
     }; 
    })(jQuery); 

Respuesta

8

Considere este ejemplo

var obj = { 
    foo: "bar", 
    baz: function() { 
     return this.foo; 
    } 
}; 
o = obj.baz; 
obj.baz(); // "bar" 
o(); // undefined 

si se llama a un método con obj.baz, el objeto que se encuentra detrás del punto es el contexto de la función (este hará referencia a este objeto). si almacena un método en una variable, pierde la información sobre el contexto. En ese caso, el contexto se establecerá en el objeto global.

var obj = { 
    baz: function() { 
     return this; 
    } 
}; 
o = obj.baz; 
obj.baz() === obj; // true 
o() === obj; // false 
o() === window; // true 

Es probable que un contexto adecuado sea importante para que .method funcione según lo previsto.

+0

Entiendo eso, supongo que no entiendo qué es lo que 'aplica' con esto ya que el primer parámetro ayuda a prevenir.Si hiciéramos algo similar a lo que usted ilustró anteriormente con el código de perforación de patos, 'esto', es posible que 'esto' sea una ventana, entonces, ¿qué ayuda tiene la aplicación? – mike

+0

hmmm - no tratando de ser obtuso y tal vez solo necesito investigar un poco más, pero aplicar en el código de perforación de pato toma ciegamente lo que sea que 'esto' esté configurado actualmente. No veo cómo es diferente a simplemente llamar a _old directamente. Tal vez eso es lo que me estoy perdiendo. Si hice una llamada directa a _old, ¿no sería 'esto' SIEMPRE el mismo 'este' que el código pasa a 'aplicar'? Entonces, cuál es el punto de usar apply – mike

+0

Digamos que el $ .fn.method original internamente usa otros métodos jQuery que dependen de este contexto. Llamarlo con contexto global haría inutilizables los otros métodos. También muchas funciones jQuery devuelven esto para que el encadenamiento sea posible. Si devuelve el contexto incorrecto, también se interrumpirá el encadenamiento. – Rafael

1

se pasa this porque apply() necesita el primer argumento de ser lo que debería ser this cuando se llama a la función de edad.

apply() se está utilizando para que pueda entregar fácilmente arguments que se tratarán como los argumentos de la función anterior.

Por lo tanto, al decidir qué pasar como this, ha elegido pasar lo que this se encuentra en ese contexto.

+0

La pregunta era por qué usar apply en primer lugar, no por qué entonces tiene que pasar 'this' como primer argumento, creo. –

+0

por lo que no tiene nada que ver con el contexto ni con lo que 'está' configurado, simplemente es un mecanismo fácil para pasar los argumentos a _old? – mike

+0

Bueno, cuando se usa 'apply()', debe decidir en qué 'this' se establecerá. – alex

1

Si tuviera que llamar a la función original sin apply, deje que JavaScript decida a qué vincular this, y que bien puede ser algo diferente de lo que estaría obligado si no hubiera monkeypatched/duckpunched el código original .

Al utilizar apply, se asegura de que se utiliza el valor correcto para this, p. con el que se llama la función de envoltura.

+0

pero si hice algo como f = jquery.fn._old, y luego llamé f(), 'this' sería una ventana cuando llamemos a apply. La aplicación, y tal vez estoy simplemente no entendiendo, no está impidiendo nada, pero usando ciegamente lo que sea que 'esto' esté configurado. Entonces, cuál es el punto. Estoy empezando a pensar que Alex puede tener razón, solo un mecanismo para pasar la matriz de argumentos. – mike

+0

Cuando duckpunching, desea recrear el contexto original de _old lo más cerca posible. Eso incluye asegurar que 'this' esté configurado para el mismo objeto que si se llamara _old directamente. La forma genérica de hacer esto es pasar 'this' usando' .apply() '. –

Cuestiones relacionadas