2012-01-19 6 views
10

Estoy usando objetos para el espacio de nombres de mi código JavaScript. Estos objetos suelen contener funciones que se denominan mapeo del this -pointer para el objeto mismo utilizando apply. Sin embargo, me resulta incómodo utilizar el this -pointer cada vez que deseo acceder a otras funciones o propiedades del objeto, especialmente porque en muchos casos utilizo el operador new para usar objetos funcionales de la misma forma que usaría las clases. Preferiría escribir new Line() en su lugar si new this.Line().¿Puede agregar dinámicamente variables locales a una función?

Sería estupendo si pudiera añadir variables locales a una función de la forma en que lo hace con php extract (pseudocódigo siguiente, que es un poco más complicado)

var sample_object = { 
    "some_function": function() {} 
} 

test() { 
    extract(sample_object); 
    some_function(); // imported from sample_object 
} 

es eso posible?

+3

Usted *podría* use un bloque 'with', pero no lo sugiero. También creo que se eliminó en el modo estricto de ES5. –

+1

@Rocket Me gustaría no sugerir que sea parte si pudiera :-) Es cierto que funcionaría, pero 'with' es confuso y extraño. También estoy bastante seguro de que causa problemas de rendimiento, pero no recuerdo la explicación de eso. – Pointy

+0

¿Qué pasa si pasa una matriz como argumento? – elvenbyte

Respuesta

3

Existe la controvertida with, que tiene algunos great applications, pero es ligeramente lenta y propensa a errores. Arroja un error en el modo estricto (en el que siempre debe optar) y va a quedar en desuso.

var sampleObject = { 
    someFunction: function() {}, 
    b: 10 
} 

with (sampleObject) { 
    typeof someFunction // "function" 

    var a = 42 
    var b = 20 
} 

sampleObject.a // undefined 
sampleObject.b // 20 

Tenga en cuenta, que las nuevas variables definidas en un -bloque with no será añadido al objeto. Sin embargo, si el objeto ya tenía una propiedad del mismo nombre, esta propiedad se modificaría (gracias, @Rocket).

Sólo por diversión, aquí está utilizando an implementation of extracteval (que es aún más mal que with). Puedes hacer cosas indescriptibles con él, por ejemplo, si tu objeto tiene propiedades como sampleObject['x; while (true) { alert("Hi!") }'].

+1

No puede agregar variables a un objeto en 'con', pero puede modificarlas. Verifique este ejemplo: http://jsfiddle.net/HkEVW/ –

+0

@Rocket, valiosa aclaración, ¡gracias! – katspaugh

4

Estoy bastante seguro de que eval es su única respuesta; pero hay que tener en cuenta que si hay alguna entrada fuera de su control involucrados, no es seguro

function dynamicArgs (varName, varValue) { 
    eval("var " + varName + "=" + JSON.encode(varValue)); 
    alert(a); 
} 

dynamicArgs("a", "value"); 

Se puede ver el problema con esto. ¿Cómo se supone que su función llama a la variable dinámica si no conoce su nombre? Lo codifiqué a la variable desde que lo transfiriera cuando lo llamé, pero esa no es una buena solución. La única solución sería otra eval. Deberías pensar en lo que debes hacer y si esto es útil. Pero es factible.

Aquí está en acción: http://jsfiddle.net/mendesjuan/GG3Wu/

function dynamicArgs (varName, varValue) { 
    eval('var ' + varName + "='" + varValue + "';"); 
    alert(eval(varName)); 
} 

dynamicArgs("f", "Here I am"); 

Ahora aquí está un ejemplo como lo que está haciendo, creando una variable de this.MyConstructor http://jsfiddle.net/mendesjuan/AK3WD/

var ns = { 
    MyConstructor: function(val) { 
     this.prop = val; 
    }, 

    runConstructor: function(val) { 
     var Ctor = "MyConstructor"; 
     eval('var ' + Ctor + ' = this.' + Ctor); 
     return new MyConstructor(val); 
    } 
} 


alert(ns.runConstructor("Hello").prop); 

Y aquí es un ejemplo, si desea importar todos los valores de un objeto al alcance;

http://jsfiddle.net/mendesjuan/AK3WD/1/

var ns = { 
    MyConstructor: function(val) { 
     this.val= val; 
    }, 

    anotherProperty: 5, 

    runConstructor: function(val) { 
     // Bring all the variables from this into this scope 
     for (var prop in this) { 
      eval('var ' + prop + ' = this.' + prop); 
     } 
     alert('Testing var anotherProperty: ' + anotherProperty); 
     var obj = new MyConstructor(val); 
     alert('Created MyConstructor: its prop is ' + obj.val) 
    } 
} 


ns.runConstructor("Hello"); 
2

Esto es cómo lo hice:

function smObject (object) { 
    return function() { 
     function getter(prop) { 
      return function() { 
       return this[prop]; 
      } 
     } 

     function setter(prop) { 
      return function(data) { 
       this[prop]=data; 
      } 
     } 

     for (var o = 0; o < object.length; o++) { 
      this[object[o]] = {}; 
      this['get' + object[o]] = getter(object[o]); 
      this['set' + object[o]] = setter(object[o]); 
     } 
    } 
} 

ahora se puede crear una instancia de una función como esta:

var fields = ['Name', 'Id', 'Other', '....' ] 
var MyFunction = smObject(fields); 
var myObject = new MyFunction(); 

// getter/setters 
myObject.setId(5); 
myObject.getId(); // will return 5 

Saludos, Emanouil

Cuestiones relacionadas