2016-05-17 4 views
2

ich herauszufinden versuche, wie zu erweitern:Überschreiben Sie eine Funktion in einer Funktion

var outdatedBrowser = function(options) { 
    function startStylesAndEvents() { 
    console.log("bleh"); 
    } 
} 

ich ohne sie zu berühren, den Quellcode der Bibliothek die Funktion startStylesAndEvents überschrieben versuche: https://github.com/burocratik/outdated-browser/blob/develop/outdatedbrowser/outdatedbrowser.js

Also, wenn ich nenne:

outdatedBrowser({ 
    bgColor: '#f25648', 
    color: '#ffffff', 
    lowerThan: 'transform', 
    languagePath: 'your_path/outdatedbrowser/lang/en.html' 
}) 

und verwendet die startStylesAndEvents Funktion, verwendet es Mine statt ihre ...

Danke!

Antwort

2

Ohne die ursprüngliche Quelle zu ändern? Du kannst nicht.

Das gesamte JavaScript-Scoping basiert auf Funktionen (Ignorieren let, const und class für den Moment). Wenn ein Wert innerhalb einer Funktion deklariert wird, kann er nicht außerhalb dieser Funktion aufgerufen werden, es sei denn, er wird von der Funktion zurückgegeben oder ändert einen externen Wert.

Zum Beispiel vorstellen, eine Funktion wie folgt aus:

function doStuff() { 
    var times = 10; 
    for (var i = 0; i < times; i++) { 
    doThing(i); 
    } 
} 

Ihre Frage semantisch identisch ist zu fragen, wie times zu ändern. Es kann einfach nicht gemacht werden.

2

Die innere Funktion ist in einer Schließung enthalten, auf die Sie keinen Zugriff haben. Leider (im Gegensatz zur Ideologie "Nichts ist unmöglich") ist dies zur Laufzeit nicht möglich.

0

Das könnte man als "private" Funktion bezeichnen. Die Funktion wird wie jede andere Variable gespeichert. In JavaScript bedeutet das in der Regel, dass es sich um einen lokalen Bereich handeln muss (anstelle einer Membervariablen), sodass es nicht überschrieben werden kann. (wenn sie nur this.functionName verwendet hätten ... dann könnte man sie leichter überschreiben)

Die gute Nachricht ist, dass es einen Hack gibt, der Cross-Browser-kompatibel zu sein scheint. (getestet in IE 11, mit Emulationsoptionen zurück auf IE 5!) In JavaScript können Sie den eigentlichen 'Quellcode' der Funktion selbst ersetzen. (Ein bisschen anders als eine richtige Überschreibung)

var newInnerFunction = function() { // intentionally anonymous for use in eval 
} 
var overriddenFunction = eval(
    outdatedBrowser.toString() // expecting outdatedBrowser to be anonymous for use in eval 
    .replace('{', '{var startStylesAndEvents=' + newInnerFunction.toString() + ';') 
) 

Beachten Sie, dass outdatedBrowser ist eine anonyme Funktion (einfach function()). Wenn es benannt würde, hätte die Verwendung von eval den Nebeneffekt, dass die neue Funktion dem Namensraum unter seinem ursprünglichen Namen hinzugefügt wird. Eine zusätzliche replace könnte dafür sorgen, wenn es ein Problem wäre.

0

Höchstwahrscheinlich können Sie nicht. Aber es ist nicht völlig unmöglich.

Zum Beispiel, wenn Sie startStylesAndEvents in einer with Anweisung, deren Umfang Objekt aufrufen hat nach außen

var scope = Object.create(null); 
var outdatedBrowser = function(options) { 
    function startStylesAndEvents() { 
    console.log("bleh"); 
    } 
    with(scope) { 
    startStylesAndEvents(); // You expect this to be the private function above 
    } 
} 
outdatedBrowser(); // "bleh" 

Dann durchgesickert, können Sie Anrufe auf startStylesAndEvents kapern:

scope.startStylesAndEvents = function() { 
    console.log("blah"); 
}; 
outdatedBrowser(); // "blah" 

Do not mach das natürlich. Es ist böse, langsam und im strikten Modus nicht erlaubt.

+3

Leider erfordert dies "den Quellcode der Bibliothek zu berühren", was für das OP nicht funktionieren wird. –

+0

@GeorgeBailey Nicht unbedingt. Die Frage sagt nicht, wie die Bibliothek die Funktion aufruft. Wenn die Bibliothek diese Funktion innerhalb einer 'with'-Anweisung aufruft, deren Bereichsobjekt nach außen geleakt wurde, müssen Sie die Bibliothek nicht ändern. Sehr unwahrscheinlich, aber nicht unmöglich. – Oriol

+0

Ich denke, OP vermeidet die Änderung 'veralteter Browser'. –