2015-06-30 16 views
9

Ich muss eine Funktion in JavaScript mock aufrufen. Dafür bin ich „Speichern“ die Funktion in einer temporären Variablen, aktualisieren Sie das Ziel mit einem neuen Funktionsblock, das Ziel aufrufen und dann die Wiederherstellung der alten Funktion:Überschreiben und Wiederherstellen einer Funktion

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

Dies funktioniert wie erwartet: Die Funktion wird überschrieben und anschließend erfolgreich wiederhergestellt. Mein Gedanke war, diesen Code in eine Hilfsfunktion zu bewegen und es leicht bei Bedarf verwenden:

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

Dieser Code wird jedoch nicht den aktuellen Zustand speichern, noch es die gezielte Funktion zu ersetzen. Was fehlt mir hier? Wird eine Funktion nicht immer als Referenz übergeben? Was sind die Hauptunterschiede zwischen den beiden Code-Snippets?

(JSFiddle zur Verfügung, aber die Vorbereitungen für 8 alert s ...)

Edit: ein Kerl Benutzer hat darauf hingewiesen, dass das zweite Verfahren nicht wirklich von der ersten unterscheiden und dass es wahrscheinlich nicht der Mühe wert Erstellen der zusätzlichen Klasse; während ich mit ihren Argumenten nicht verstehen und akzeptieren, sehe ich zwei Vorteile bei der zweiten Methode (beide insbesondere, realen Fall meiner Anwendung):

  1. es ist einfacher/schneller swapp.Restore(); als myNameSpace.level2.level3.level4.level5 = swap; zu schreiben, wenn Arbeits mit Objekten, die mehrere Ebenen von Kindelementen haben, und
  2. abstrahiert die Operation, die eine konsistente Verwendung innerhalb des Entwicklungsteams bietet (zusätzlich könnte Protokollierung oder Typprüfung innerhalb der Klasse erfolgen).

Antwort

5

Dies geschieht, weil target nicht um eine echte Referenz ist, ist es ein Wert, der target Funktion verweist.

Wenn Sie das Ziel jedoch neu zuweisen, ändern Sie nicht den gehaltenen Wert (den Verweis auf die Funktion), sondern Sie ändern den Wert direkt, was bedeutet, dass Sie dies nicht tun können.

Stattdessen können Sie das Objekt übergeben, das die zu ersetzende Funktion enthält (es würde nur mit einem Objekt funktionieren, da Sie später darauf zugreifen müssen).

Hier ist, was ich mit

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, schlagen Sie mich nach 15 Sekunden scheinbar mit einer fast identischen Antwort! – mGuv

3

Die FunctionSwapper seine eigene Kopie der Wiederherstellung der Funktion, aber es hat keine Verbindung zum myObject (Sie es nicht einen Verweis auf myObject passieren).

funktionieren würde diese:

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

ich in myObject.myFunc, indem man glauben kam, Sie tatsächlich die Referenz aus der myObject zu brechen, ist es nicht aktualisiert so nicht tatsächlich die myFunc Aufruf von myObject, aktualisiert sie die lokaler Umfang der FunctionSwapper Kopie.

Vergleichen Sie es mit dieser, die auf das Objekt, das den Betrieb führt selbst:

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