2015-06-30 16 views
9

Devo fingere di chiamare una funzione in JavaScript. Per questo, sto "salvare" la funzione in una variabile temporanea, aggiornare il bersaglio con un nuovo blocco funzionale, chiamando il bersaglio e poi ripristinare la vecchia funzione:Sovrascrivi e ripristina una funzione

var myObject = { 
 
    myIntProp: 1, 
 
    myFunc: function(value) { 
 
    alert(value + 1); 
 
    } 
 
}; 
 
myObject.myFunc(2); 
 

 
var tmp = myObject.myFunc; 
 
myObject.myFunc = function(value) { 
 
    alert(value - 1); 
 
}; 
 
myObject.myFunc(2); 
 

 
myObject.myFunc = tmp; 
 
myObject.myFunc(2);

questo funziona come previsto: la funzione viene sovrascritta e quindi ripristinata con successo. Il mio pensiero è stato quello di spostare il codice in una funzione di supporto e di usare facilmente quando necessario:

function FunctionSwapper(target, newFunction) { 
 
    var old = target; 
 
    target = newFunction; 
 
    this.Restore = function() { 
 
    target = old; 
 
    } 
 
}; 
 

 
var myObject = { 
 
    myIntProp: 1, 
 
    myFunc: function(value) { 
 
    alert(value + 1); 
 
    } 
 
}; 
 
myObject.myFunc(2); 
 

 
var swapp = new FunctionSwapper(myObject.myFunc, function(value) { 
 
    alert(value - 1); 
 
}); 
 
myObject.myFunc(2); 
 

 
swapp.Restore(); 
 
myObject.myFunc(2);

Questo codice tuttavia, non salva lo stato attuale né è sostituendo la funzione mirata. Cosa mi manca qui? Una funzione non è sempre passata come riferimento? Quali sono le principali differenze tra i due frammenti di codice?

(JSFiddle disponibili, ma prepararsi a 8 alert s ...)

Edit: un utente collega ha fatto notare che il secondo metodo in realtà non differisce dalla prima e che probabilmente non vale la pena di creare la classe aggiuntiva; mentre io capisco e condivido le loro argomentazioni, vedo due vantaggi nel secondo metodo (entrambi si applicano al mio particolare, caso nel mondo reale):

  1. è più facile/più veloce per scrivere swapp.Restore(); di myNameSpace.level2.level3.level4.level5 = swap; quando si lavora con oggetti che hanno diversi livelli di elementi figlio e,
  2. , astrae l'operazione, fornendo un uso coerente tra il team di sviluppo (in aggiunta, la registrazione o il tipo di correzione può essere fatto all'interno della classe).

risposta

5

Questo accade perché target non è un vero e proprio riferimento, è un valore che fa riferimento target funzione.

Tuttavia, quando si riassegna il target, non si modifica il valore mantenuto (il riferimento alla funzione), ma si modifica direttamente il valore, il che significa che non è possibile farlo in questo modo.

Invece è possibile passare l'oggetto che contiene la funzione da sostituire (funzionerebbe solo con un oggetto, poiché è necessario accedervi in ​​seguito).

Ecco quello che mi si avvicinò con

function FunctionSwapper(target, name, newFunction) { 
    var old = target[name]; 
    target[name] = newFunction; 
    this.Restore = function() { 
    target[name] = old; 
    } 
}; 

var myObject = { 
    myIntProp: 1, 
    myFunc: function(value) { 
    alert(value + 1); 
    } 
}; 
myObject.myFunc(2); 

var swapp = new FunctionSwapper(myObject, 'myFunc', function(value) { 
    alert(value - 1); 
}); 
myObject.myFunc(2); 

swapp.Restore(); 
myObject.myFunc(2); 
+0

Ah, mi hai battuto di 15 secondi, a quanto pare con una risposta quasi identica! – mGuv

3

Il FunctionSwapper sta ripristinando la propria copia della funzione, ma non ha alcuna connessione con myObject (non si passa un riferimento a myObject).

questo dovrebbe funzionare:

function FunctionSwapper(object,name,newFunction) { 
    var old = object[name]; 
    object[name] = newFunction; 
    this.Restore = function() { 
    object[name] = old; 
    } 
}; 

...

var swapp = new FunctionSwapper(myObject, "myFunc", function(value) { 
    alert(value - 1); 
}); 
3

Credo passando myObject.myFunc, in realtà rompere il riferimento dal myObject, quindi in realtà non aggiornare il myFunc chiamata del myObject, aggiorna la ambito locale della copia di FunctionSwapper.

confrontarlo con questo, che svolge l'operazione sull'oggetto stesso:

function FunctionSwapper(obj, funcName, newFunction) { 
    var old = obj[funcName]; 
    obj[funcName] = newFunction; 
    this.Restore = function() { 
     obj[funcName] = old; 
    } 
}; 

var myObject = { 
    myIntProp: 1, 
    myFunc: function(value) { 
    alert(value + 1); 
    } 
}; 
myObject.myFunc(2); 

var swapp = new FunctionSwapper(myObject, "myFunc", function(value) { 
    alert(value - 1); 
}); 
myObject.myFunc(2); 

swapp.Restore(); 
myObject.myFunc(2);