Nadpisywanie funkcji JavaScript podczas odwoływania się do oryginału
Mam funkcję a()
, którą chcę nadpisać, ale chcę również, aby oryginalna a()
była wykonywana w kolejności zależnej od kontekstu. Na przykład, czasami, gdy generuję stronę, będę chciał nadpisać Tak:
function a() {
new_code();
original_a();
}
I czasami tak:
function a() {
original_a();
other_new_code();
}
Jak mam to zdobyć original_a()
z przejazdu a()
? Czy to w ogóle możliwe?
Proszę nie sugerować alternatywy dla nadmiernej jazdy w ten sposób, wiem o wielu. Pytam o ten sposób konkretnie.
11 answers
Mógłbyś zrobić coś takiego:
var a = (function() {
var original_a = a;
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})();
Deklaracja original_a
wewnątrz funkcji anonimowej zapobiega zaśmiecaniu globalnej przestrzeni nazw, ale jest dostępna w funkcjach wewnętrznych.
Jak wspomniał Nerdmaster w komentarzach, pamiętaj, aby dołączyć ()
na końcu. Chcesz wywołać funkcję zewnętrzną i zapisać wynik (jedną z dwóch funkcji wewnętrznych) w a
, a nie przechowywać samą funkcję zewnętrzną w a
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-21 22:33:50
Wzór Proxy może Ci pomóc:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
Powyższy kod zawija w funkcję ukrywającą zmienną "proxied". Zapisuje metodę setArray jQuery w zamknięciu i nadpisuje ją. Następnie proxy rejestruje wszystkie wywołania metody i przekazuje wywołanie do oryginału. Użycie apply (this, arguments) gwarantuje, że wywołujący nie będzie w stanie zauważyć różnicy między oryginalną i proxyowaną metodą.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 22:57:53
Dzięki chłopaki the proxy pattern naprawdę pomógł.....Właściwie to chciałem nazwać globalną funkcję foo.. Na niektórych stronach muszę zrobić kilka kontroli. Więc zrobiłem następujące rzeczy.
//Saving the original func
var org_foo = window.foo;
//Assigning proxy fucnc
window.foo = function(args){
//Performing checks
if(checkCondition(args)){
//Calling original funcs
org_foo(args);
}
};
Thnx to naprawdę mi pomogło
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 22:58:23
Możesz nadpisać funkcję używając konstrukcji takiej jak:
function override(f, g) {
return function() {
return g(f);
};
}
Na przykład:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a(); }
else { original_a(); other_new_code(); }
});
Edit: Poprawiono literówkę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 12:02:40
Przekazywanie arbitralnych argumentów:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a.apply(this, arguments) ; }
else { original_a.apply(this, arguments); other_new_code(); }
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 17:24:27
Powyższe przykłady nie stosują poprawnie this
lub przekazują arguments
do nadpisania funkcji. Podkreślenie _.wrap() zawija istniejące funkcje, stosuje this
i przekazuje arguments
poprawnie. Zobacz: http://underscorejs.org/#wrap
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 15:44:27
Odpowiedź, którą zapewnia @Matthew Crumley, polega na wykorzystaniu bezpośrednio wywołanych wyrażeń funkcji, aby zamknąć starszą funkcję " a " w kontekście wykonywania zwracanej funkcji. Myślę, że to była najlepsza odpowiedź, ale osobiście wolałbym przekazać funkcję "a" jako argument do życia. Myślę, że to jest bardziej zrozumiałe.
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-17 12:49:40
Miałem jakiś kod napisany przez kogoś innego i chciałem dodać linię do funkcji, której nie mogłem znaleźć w kodzie. Więc jako obejście chciałem to obejść.
Jednak żadne z rozwiązań nie zadziałało.Oto co zadziałało w moim przypadku:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 22:54:28
Stworzyłem mały helper dla podobnego scenariusza, ponieważ często musiałem nadpisywać funkcje z kilku bibliotek. Ten Pomocnik akceptuje "przestrzeń nazw" (kontener funkcji), nazwę funkcji i funkcję nadrzędną. Zastąpi oryginalną funkcję w wymienionej przestrzeni nazw nową.
Nowa funkcja przyjmuje oryginalną funkcję jako pierwszy argument, a oryginalne argumenty funkcji jako resztę. Zachowa kontekst za każdym razem. Informatyka obsługuje również funkcje void i non-void.
function overrideFunction(namespace, baseFuncName, func) {
var originalFn = namespace[baseFuncName];
namespace[baseFuncName] = function () {
return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
};
}
Użycie na przykład z Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
// ... do stuff before base call
baseFn(obj);
// ... do stuff after base call
});
Nie stworzyłem jednak żadnych testów wydajnościowych. Może to ewentualnie dodać niechciane koszty, które mogą lub nie mogą być wielką sprawą, w zależności od scenariuszy.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 22:57:35
Moim zdaniem najlepsze odpowiedzi nie są czytelne/utrzymywalne, a pozostałe odpowiedzi nie wiążą odpowiednio kontekstu. Oto czytelne rozwiązanie wykorzystujące składnię ES6 do rozwiązania obu tych problemów.
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 01:41:10
Więc moja odpowiedź okazała się rozwiązaniem, które pozwala mi użyć zmiennej _this wskazującej na oryginalny obiekt. I utworzyć nową instancję "kwadrat" jednak nienawidziłem sposób "kwadrat" generowane jego rozmiar. Pomyślałem, że powinno być zgodne z moimi konkretnymi potrzebami. Jednak w tym celu potrzebowałem, aby kwadrat miał zaktualizowaną funkcję "GetSize" z wewnętrznymi funkcjami tej funkcji wywołującymi inne funkcje już istniejące w kwadracie, takie jak ta.wysokość, to.GetVolume (). Ale w tym celu Musiałem to zrobić bez żadnych szalonych hacków. Oto moje rozwiązanie.
Jakaś inna funkcja inicjalizująca lub pomocnicza obiekt.
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
Funkcja w innym obiekcie.
updateToolbarButtons = function(viewer) {
var _viewer = viewer;
return function(width, height){
blah blah black sheep I can refer to this.anything();
}
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-30 06:17:05