2015-06-30 13 views
9

Muszę wyśmiać wywołanie funkcji w JavaScript. Do tego mam „oszczędność” funkcja w zmiennej tymczasowej, zaktualizuj cel z nowego bloku funkcyjnego, nazywając cel, a następnie przywracając starą funkcję:Zastępuje i przywraca funkcję

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

to działa zgodnie z oczekiwaniami: funkcja zostanie nadpisana, a następnie pomyślnie przywrócona. Moja myśl była, aby przenieść ten kod do funkcji pomocniczych i łatwo go używać, gdy są potrzebne:

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

Kod ten jednak nie zapisać aktualny stan ani nie jest zastąpienie funkcji docelowej. Czego tu mi brakuje? Czy funkcja nie jest zawsze przekazywana jako odniesienie? Jakie są główne różnice między tymi dwoma fragmentami kodu?

(JSFiddle dostępne, ale przygotowania do 8 alert s ...)

Edycja: użytkownik kolega zauważył, że druga metoda nie bardzo różnią się od pierwszej, a to chyba nie warta tworzenia dodatkowej klasy; a ja nie rozumiem i zgadzam się z ich argumentami, widzę dwie zalety w drugiej metody (oba dotyczą mojego szczególności, sprawa w świecie rzeczywistym):

  1. łatwiej/szybciej pisać swapp.Restore(); niż myNameSpace.level2.level3.level4.level5 = swap; podczas pracy z obiektami z kilkoma poziomami elementów potomnych i,
  2. , abstrahuje operację, zapewniając spójne wykorzystanie wśród zespołu programistów (dodatkowo, rejestrowanie lub sprawdzanie typu może być wykonane wewnątrz klasy).

Odpowiedz

5

Dzieje się tak dlatego target nie jest prawdziwym odniesienia, jest to wartość, która odwołuje target funkcję.

Jednak przy ponownym przypisywaniu celu nie modyfikuje się wartości zatrzymanej (odniesienie do funkcji), ale bezpośrednio modyfikuje się wartość, co oznacza, że ​​nie można tego zrobić w ten sposób.

Zamiast tego można przekazać obiekt, który ma funkcję do zastąpienia (działałby tylko z obiektem, ponieważ trzeba uzyskać do niego dostęp później).

Oto co wymyśliłem

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, ty mnie pokonać przez 15 sekund, widocznie z niemal identycznym odpowiedź! – mGuv

3

The FunctionSwapper jest przywrócenie własną kopię funkcji, ale nie ma połączenia myObject (nie przekazać go odniesienie do myObject).

to będzie działać:

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

wierzę, przekazując myObject.myFunc, to rzeczywiście przełamać odwołanie od myObject, więc faktycznie nie aktualizuje myFunc wezwanie myObject, że aktualizuje lokalny zasięg kopii FunctionSwapper.

porównać go z tym, który wykonuje operację na obiekcie samego:

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); 
Powiązane problemy