2009-07-08 15 views
16

Estoy tratando de entender los principios de la cadena de funciones estilo jQuery directamente en mi cabeza. Con esto quiero decir:¿Cómo funciona el encadenamiento básico de objeto/función en javascript?

var e = f1('test').f2().f3(); 

Tengo un ejemplo para trabajar, mientras que otro no. Voy a publicar los de abajo. Siempre quiero aprender los primeros principios fundamentales de cómo funciona algo para poder construir sobre eso. Hasta ahora, solo he tenido un conocimiento superficial y poco claro de cómo funciona el encadenamiento y me estoy encontrando con errores que no puedo resolver inteligentemente.

lo que sé:

  1. Las funciones tienen que volver a sí mismos, también conocido como "devolver este;"
  2. Las funciones encadenables deben residir en una función principal, también conocida como jQuery, .css() es un método secundario de jQuery(), por lo tanto jQuery(). Css();
  3. La función primaria debe devolverse o una nueva instancia de sí mismo.

Este ejemplo práctico:

var one = function(num){ 
    this.oldnum = num; 

    this.add = function(){ 
     this.oldnum++; 
     return this; 
    } 

    if(this instanceof one){ 
     return this.one;  
    }else{ 
     return new one(num);  
    } 
} 
var test = one(1).add().add(); 

Pero éste no:

var gmap = function(){ 

    this.add = function(){ 
     alert('add'); 

     return this;  
    } 

    if(this instanceof gmap) { 
     return this.gmap; 
    } else{ 
     return new gmap(); 
    } 

} 
var test = gmap.add(); 
+6

Las funciones no se devuelven a sí mismas, devuelven el objeto que admite los métodos que está encadenando. En el caso jQuery, es el nodo que se está operando. – drudru

+1

Haga que cada función termine con un 'return this;'. –

+0

@MarcB - Lo sé, pero ¿cómo? –

Respuesta

32

en las funciones de JavaScript son los primeros objetos de la clase. Cuando defines una función, es el constructor para ese objeto de función. En otras palabras:

var gmap = function() { 
    this.add = function() { 
     alert('add'); 
    return this; 
    } 

    this.del = function() { 
     alert('delete'); 
     return this; 
    } 

    if (this instanceof gmap) { 
     return this.gmap; 
    } else { 
     return new gmap(); 
    } 
} 
var test = new gmap(); 
test.add().del(); 

asignando el

new gmap();
a la prueba variable que ya ha construido un nuevo objeto que "hereda" todas las propiedades y métodos de la gmap() Constructor (clase). Si ejecuta el fragmento de arriba, verá una alerta para "agregar" y "eliminar".

En sus ejemplos anteriores, el "esto" se refiere al objeto ventana, a menos que ajuste las funciones en otra función u objeto.

Me resulta difícil entender el encadenamiento al principio, al menos lo fue para mí, pero una vez que lo entendí, me di cuenta de lo poderosa que puede ser una herramienta.

4

Lamentablemente, la respuesta directa tiene que ser 'no'. Incluso si se puede reemplazar los métodos existentes (que es probable que pueda en muchos UA, pero sospecho que no puede en IE), todavía estaría atrapado con cambios de nombre desagradables:

HTMLElement.prototype.setAttribute = function(attr) { 
    HTMLElement.prototype.setAttribute(attr) //uh-oh; 
} 

La mejor que probablemente podría salirse con la suya está utilizando un nombre diferente:

HTMLElement.prototype.setAttr = function(attr) { 
    HTMLElement.prototype.setAttribute(attr); 
    return this; 
} 
+0

¡Parece que me quedaré con jQuery para encadenar! –

+1

Tenga en cuenta que esta respuesta es a [una pregunta diferente] (http://stackoverflow.com/questions/10965781) – kojiro

1

"reescribir" una función, pero aún así ser capaz de utilizar la versión original, primero debe asignar la función original a una variable diferente. Asumir un objeto ejemplo:

function MyObject() { }; 

MyObject.prototype.func1 = function(a, b) { }; 

para reescribir func1 para chainability, hacer esto:

MyObject.prototype.std_func1 = MyObject.prototype.func1; 
MyObject.prototype.func1 = function(a, b) { 
    this.std_func1(a, b); 
    return this; 
}; 

Aquí hay una working example. Solo necesita emplear esta técnica en todos los objetos estándar que considere necesarios para ser chainable.

En el momento en que hace todo este trabajo, es posible darse cuenta de que hay mejores maneras de lograr lo que estás tratando de hacer, como el uso de una biblioteca que ya ha construido en chainability. * tos * jQuery * tos *

+0

Aquí hay una solución general: http://stackoverflow.com/a/15797662/162793 – sheldonh

-3

Simplemente llame al método como var test = gmap(). add();

como gmap no es una función de una variable

+0

Esto no funcionará porque 'add' no está definido en' gmap() ', sino solo en' new gmap() '. –

0

En primer lugar, permítanme decir que estoy explicando esto en mis propias palabras.

El método de encadenamiento es más o menos un método de invocación del objeto devuelto por otra función/método. por ejemplo (usando jquery):

función
$('#demo'); 

este jquery selecciona y devuelve un objeto jquery el elemento DOM con la demo ID. si el elemento era un nodo de texto (elemento), podríamos encadenar un método del objeto que se devolvió. por ejemplo:

$('#demo').text('Some Text'); 

Por lo tanto, siempre que una función/método devuelve un objeto, se pueden encadenar un método del objeto devuelto a la declaración original.

En cuanto a por qué este último no funciona, preste atención a dónde y cuándo se utiliza la palabra clave this. Es muy probable que sea un problema de contexto. Cuando llame al this, asegúrese de que this hace referencia a ese objeto de función en sí, no al objeto de ventana/alcance global.

Espero que ayude.

Cuestiones relacionadas