2012-01-19 13 views
10

Sto usando gli oggetti per assegnare un nome al mio codice JavaScript. Questi oggetti di solito contengono funzioni chiamate mapping del this -pointer all'oggetto stesso utilizzando apply. Tuttavia, trovo scomodo utilizzare il parametro this ogni volta che desidero accedere ad altre funzioni o proprietà dell'oggetto, specialmente perché in molti casi uso il new -operator per usare gli oggetti funzione nel modo in cui usereste le classi. Preferirei scrivere new Line() invece se new this.Line().È possibile aggiungere dinamicamente variabili locali a una funzione?

Sarebbe bello se si potesse aggiungere le variabili locali a una funzione del modo in cui lo fa con php extract (segue pseudocodice, è un po 'più complicato)

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

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

è che anche possibile?

+3

È *poteva* usa un blocco 'with', ma non lo suggerisco. Penso inoltre che sia stato rimosso in modalità rigorosa ES5. –

+1

@Rocket Mi piacerebbe non aggiungere la parte se potessi :-) È vero che funzionerebbe, ma 'with' è confuso e strano. Inoltre sono abbastanza sicuro che causi problemi di prestazioni, ma non riesco a ricordare la spiegazione per questo. – Pointy

+0

Cosa succede se si passa un array come argomento? – elvenbyte

risposta

3

C'è il controverso with, che ha qualche great applications, ma è marginalmente lento e soggetto a errori. Genera un errore nella modalità rigorosa (che dovresti sempre attivare) e sarà deprecato.

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

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

    var a = 42 
    var b = 20 
} 

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

nota, che le nuove variabili definite in una with -block non verrà aggiunto all'oggetto. Tuttavia, se l'oggetto avesse già una proprietà omonima, questa proprietà sarebbe stata modificata (grazie, @Rocket).

Solo per divertimento, ecco an implementation of extract utilizzando eval (che è ancora più male che with). Puoi fare cose inesprimibili con esso, per esempio se il tuo oggetto ha proprietà come sampleObject['x; while (true) { alert("Hi!") }'].

+1

Non è possibile aggiungere variabili a un oggetto in 'with', ma è possibile modificarle. Guarda questo esempio: http://jsfiddle.net/HkEVW/ –

+0

@Rocket, preziosi chiarimenti, grazie! – katspaugh

4

Sono sicuro che eval è la tua unica risposta; ma è necessario essere consapevoli del fatto che se non c'è alcun ingresso al di fuori del vostro controllo in questione, non è sicuro

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

dynamicArgs("a", "value"); 

Si può vedere il problema con questo. In che modo la tua funzione dovrebbe chiamare la variabile dinamica se non conosce il suo nome? L'ho codificato su una variabile da quando l'ho passata quando la chiamavo, ma non è una buona soluzione. L'unica soluzione sarebbe un altro eval. Dovresti davvero pensare a cosa devi fare e se questo è utile. Ma è fattibile.

Qui è in azione: http://jsfiddle.net/mendesjuan/GG3Wu/

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

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

Ora qui è un esempio come quello che stai facendo, creando una variabile da 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); 

Ed ecco un esempio se si voleva per importare tutti i valori da un oggetto nello scope;

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

Ecco come ho fatto:

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]); 
     } 
    } 
} 

ora è possibile creare un'istanza di una funzione come questa:

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

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

saluti, Emanouil

Problemi correlati