2011-03-30 25 views
11

En cuanto a la fábrica del aparato UI de jQuery ...cómo declarar una variable estática/clase en un widget de widget de fábrica de jQuery UI

¿Cuál es la mejor manera de tener una variable de nivel variable estática/clase que se comparte entre todos ¿instancias?

p. Ej.

 
$.widget("ui.staticTest", { 
    staticVar:'unchanged', 
    test: function(a){ 
     if(a){ 
      this.staticVar= a; 
     } 
     alert(JSON.stringify(this.staticVar)); 
    } 
}); 

$('#test').staticTest(); 
$('#parent').staticTest(); 

$('#test').staticTest('test','changed'); 
$('#parent').staticTest('test'); 

en lo anterior, si staticVar eran estáticas, $ ('# matriz) staticTest ('test').; alertaría 'cambiado' pero en su lugar alerta 'sin cambios'.

(este código está en jsFiddle si quieres tener una obra de teatro: http://jsfiddle.net/alzclarke/Sx8pJ/)

Las soluciones que se me ocurre a mí mismo son feas:.

1) $ ('cuerpo') de datos ('sharedVariable ', myData) - esto no parece una buena práctica, ¿qué pasa si alguien o algo borra el cuerpo de datos 2) lo almacena en el espacio de nombres del prototipo, por ejemplo, = $ .ui.staticTest.prototype.staticVar = myData; esto también suena las campanas de alarma

Respuesta

24

cierres es su respuesta

(function($) { 

var staticVariable = ''; 

$.widget('ui.newWidget', { 
    options: { 

    }, 
    _init: function() { 
    } 

}); 

})(jQuery); 

staticVariable sólo estará disponible en el ámbito del widget que acaba de definir, ya que está envuelto en una función anónima que se llama de inmediato (como usted ya debería estar haciendo para su jQuery/jquery ui plugins.

+1

esta es una gran respuesta, tan simple, y a diferencia de las otras respuestas, permite que las variables estáticas sean verdaderamente privadas. – alzclarke

+2

¿Puedo preguntar cómo se podría acceder (establecer) a staticVariable desde fuera del widget? Necesito una opción que sea configurable una vez para todas las instancias de widgets. – Marc

+0

puede hacer una función para hacerlo y hacer que tenga alcance global –

0

parece un poco malentendido sobre la palabra clave "this". Aquí esta palabra clave hace que esa variable sea específica de la instancia. Pruebe el siguiente código.

$.widget("ui.staticTest", { 
    staticVar:'unchanged', 
    test: function(a){ 
     if(a){ 
      staticVar= a; 
     } 
     alert(JSON.stringify(staticVar)); 
    } 
}); 

$('#test').staticTest(); 
$('#parent').staticTest(); 

$('#test').staticTest('test','changed'); 
$('#parent').staticTest('test'); 
+0

@alzclarke, lo intenté, me estoy "cambiando" en ambas llamadas. ¿Me falta algo? –

+0

lo siento, tienes razón! Bien pensado, en realidad el código está declarando y asignando una variable global no es una variable de clase. Si ejecuto su código con la alerta de línea (staticVar); al final, también alerta 'changed'. de manera similar, si algún código antes de la llamada usa este nombre de variable, el valor se pierde. – alzclarke

2

Parece que los widgets no tienen ámbito compartido. Lo que. Entonces, lo que haría sería definir un objeto compartido en el objeto jQuery UI en sí, como usted mismo lo propone.

Nota: el nombre del objeto compartido debe reflejar el nombre del widget y el espacio de nombres.

$.ui.staticShared = { color: "#fff" }; 

$.widget("ui.static", { 
    color: function (o) 
    { 
     if (typeof o !== "undefined") $.ui.staticShared.color = o; 

     return $.ui.staticShared.color; 
    } 
}); 

Esto es tan limpia como se pone en los ojos. Y seguro; existe el riesgo de que la gente anule el objeto compartido, pero no es como si el mundo se derrumbara si eso sucede.

Si desea algún tipo de falla/retroalimentación si el objeto compartido no es válido o ha sido anulado, puede verificar la estructura del objeto en el evento _init.

$.widget("ui.static", { 
    _init: function() 
    { 
     if (typeof $.ui.staticShared === "undefined") 
     { 
      alert("$.ui.staticShared is required for this plug-in to run"); 
     } 
    }, 
}); 

El evento se dispara _init cada vez que se crea una instancia.

+0

hola, bien pensado, pero aquí estás declarando y asignando una variable global, no una variable de clase. si ejecuto tu código con la alerta de línea (_static); al final, también alerta 'bar'. De forma similar, si un código anterior a la llamada usa este nombre de variable, el valor se pierde – alzclarke

+0

@alzclarke: Tiene razón. _Static se define en el objeto ventana. Muy bien visto :) – roosteronacid

+0

Actualizado mi respuesta. – roosteronacid

0

// Ejemplo detallado explicando las variables estáticas, de instancia y globales en el ámbito widget de

$.widget("ui.staticTest", { 
    //staticVar is an instance variable, regardless of what it is named as 
    staticVar: 'brownMamba', 

    _create: function() { 

    }, 

    //test the static variable 
    testStatic: function(a) { 
     if (a) { 
     //Here you're actually creating a new static variable called 
     //staticVar which is associated with the staticTest object as you assign 
     //value to it. 
      //Lemme show you what I mean with an example 
      //Here it alerts 'Undefined' as 'staticVar' does not exists 
      //don't confuse it with the staticVar: 'brownMamba' declared above, 
      //that one is an instance variable 
      alert("Type of $.ui.staticTest.staticVar before assignment: " + typeof $.ui.staticTest.staticVar); 

      $.ui.staticTest.staticVar = a; 
      //At this point it alerts the type of 'a', which in our case is 'string'    
      alert("Type of $.ui.staticTest.staticVar after assignment: " + typeof $.ui.staticTest.staticVar); 

      //value of instance variable at this point 
      alert("typeof this.staticVar: " + typeof this.staticVar); 
      alert("Value of this.staticVar: " + this.staticVar); 
      //value of global variable at this point 
      //'Undefined' as it does not exist 
      alert("Type of staticVar: " + typeof staticVar); //or window.staticVar 


     } else { 
      alert("value of staticVar in testStatic with no argument: " + $.ui.staticTest.staticVar); 
     } 
    }, 

    //test the instance variable 
    testInstance: function(a) { 
     if (a) { 
     //Here you're actually working with the instance variable declared above, 
     //with the value 'brownMamba' 
     //Lemme show you what I mean with an example 
     //Here it alerts 'string' as 'staticVar' exists and is assigned a string 
      alert("typeof this.staticVar is " + typeof this.staticVar + " and its 
value is " + this.staticVar); 

      this.staticVar = a; 
      alert("typeof this.staticVar after assignment is " + typeof this.staticVar); 
      alert("Value of this.staticVar after assignment is " + this.staticVar); 
     } else { 
      alert("value of this.staticVar in testInstance with no argument: " + this.staticVar); 
     } 
    }, 

    //test the Global variable 
    testGlobal: function(a) { 
     if (a) { 
     /*Here you're actually creating a global variable called staticVar*/ 
      //Lemme show you what I mean with an example 
      //Here it alerts 'Undefined' as 'staticVar' does not exists 
      alert("Type of staticVar before assignment: " + typeof staticVar); 

      staticVar = a; //creating a global variable, which will be declared 
in window scope, i.e. window.staticVar 
      //At this point it alerts the type of a, which in our case is a 'string'    
      alert("Type staticVar after assignment: " + typeof staticVar); 
      alert("Value of staticVar after assignment: " + staticVar) 
     } else { 
      alert("value of staticVar in testGlobal with no argument: " + staticVar); 
     } 
    } 
}); 

//instantiating widget 
$('#test').staticTest(); 
//instantiating widget 
$('#parent').staticTest(); 

$('#test').staticTest('testStatic', 'changed'); 
//value will be sustained as its associated to the object 
$('#parent').staticTest('testStatic'); 

$('#test').staticTest('testInstance', 'bluemamba'); 
//here the value doesn't change as its an instance variable and its value is not altered 
$('#parent').staticTest('testInstance'); 

$('#test').staticTest('testGlobal', 'bluemamba'); 
//here the value is still sustained as the global is created in the previous call 
$('#parent').staticTest('testGlobal'); 

http://jsfiddle.net/hiteshubharani/z5k4E/6/

+0

hola, la solución de gallo es básicamente utilizar una variable global, pero con un espacio de nombres administrado. por lo tanto, realmente no necesita referenciarlo en el constructor. He modificado su solución – alzclarke

+0

alzclarke, Hubiera apreciado que agregue su propia respuesta en lugar de modificar por completo mi publicación. – brownmamba

+0

@brownmamba lo suficientemente justo, he revertido mi edición y he añadido una nueva respuesta, soz, ¡no quise ofender! – alzclarke

1

en realidad, si la variable es un objeto, éste es automáticamente estática ... hmmmmmmmm muy útil! (no) ... especialmente considerando que las variables que contienen primitivos muestran el comportamiento opuesto. Debe tener algo que ver con el viejo modismo de "el puntero no es el objeto".

ANYWHO ...

Si la variable contiene un objeto {} Las siguientes SERÁ LA RESPUESTA CORRECTA, lo contrario, consulte las otras respuestas:

Ejemplo STATIC:

$.widget("ui.staticTest", { 
    staticVar:{val:'unchanged'}, 
    _create: function(){ 
    }, 
    test: function(a){ 
     if(a){ 
      this.staticVar.val= a; 
     } 
     alert(JSON.stringify(this.staticVar.val)); 
    } 
}); 


$('#test').staticTest(); 
$('#parent').staticTest(); 

$('#test').staticTest('test','changed'); 
$('#parent').staticTest('test'); 

http://jsfiddle.net/alzclarke/Sx8pJ/9/

NO STATIC Ejemplo:

$.widget("ui.staticTest", { 
    _create: function(){ 
     this.staticVar={val:'unchanged'}; 
    }, 
    test: function(a){ 
     if(a){ 
      this.staticVar.val= a; 
     } 
     alert(JSON.stringify(this.staticVar.val)); 
    } 
}); 


$('#test').staticTest(); 
$('#parent').staticTest(); 

$('#test').staticTest('test','changed'); 
$('#parent').staticTest('test'); 

http://jsfiddle.net/alzclarke/Sx8pJ/10/

+0

Tome nota de este ejemplo si busca variables de instancia complejas: los tipos primitivos son únicos por instancia del widget, pero los tipos de objeto se comparten entre las instancias. Si necesita tipos de objetos instancia, hágalos parte de esto.opciones, que siempre es específico de la instancia –

+0

sí - excepto cuando esto viola la encapsulación, en cuyo caso su otra opción es declarar la variable del objeto en los métodos _create o _init. – alzclarke

+1

Las variables estáticas a menudo son constantes, que por convención tendrían nombres ALL_CAPS. Es irónico que las únicas ALL_CAPS que veo en esta página se encuentran en esta respuesta shouty. –

0

sencilla implimentation de soludion de gallo:

$.widget("ui.staticTest", { 
test: function(a){ 
    if(a){ 
     $.ui.staticTest.staticVar= a; 
    } 
    alert(JSON.stringify($.ui.staticTest.staticVar)); 
} 
}); 
$.ui.staticTest.staticVar = 'unchanged'; 


$('#test').staticTest(); 
$('#parent').staticTest(); 
$('#test').staticTest('test'); 
$('#test').staticTest('test','changed'); 
$('#parent').staticTest('test'); 
0

podría utilizar el patrón de JS general de encapsulación:

$.widget("ui.staticTest", (function() { 

    staticVar:'unchanged'; 

    return { 
     test: function(a){ 
      if(a){ 
       staticVar= a; 
      } 
      alert(JSON.stringify(staticVar)); 
     } 
    }; 
}())); 

Tenedor de su jsFiddle en: http://jsfiddle.net/pettys/RwKdZ/

Pro: nada mágico pasando, sin jugar con el espacio jQuery en absoluto. Con: introduce su widget en otro nivel.

Cuestiones relacionadas