Przekazywanie funkcji z parametrami jako parametrem?


151

Czy można przekazać funkcję javascript z parametrami jako parametrem?

Przykład:

$(edit_link).click( changeViewMode( myvar ) );

5
Wygląda jak JQuery i najprawdopodobniej tak, ale to nie ma znaczenia. Użycie lub parametry i funkcje są takie same, niezależnie od używanych bibliotek JavaScript.
Guffa,

@Guffa - zastanawiałem się, czy powinien być oznaczony tagiem jQuery
Russ Cam

1
@Lucia Proszę rozważyć zmianę zaakceptowanej odpowiedzi na to .
Michał Perłakowski

Jeśli pracujesz z Reactem, rozważ stackoverflow.com/questions/41369497/ ...
Michael Freidgeim

Odpowiedzi:


244

Użyj „zamknięcia”:

$(edit_link).click(function(){ return changeViewMode(myvar); });

Tworzy to anonimowe opakowanie funkcji tymczasowej, które wie o parametrze i przekazuje go do rzeczywistej implementacji wywołania zwrotnego.


3
Jeśli chcesz wywołać funkcję na obiekcie, musisz wywołać bind (). myObj.click (function () {this.doSomething ();} .bind (myObj)); Dzięki temu „this” będzie myObj.
Eli

1
Czy nie jest to problem z wydajnością, gdy mamy do czynienia z wieloma z nich? Np. Renderujesz onPress w rzędzie i masz 10000 wierszy. Spowoduje to utworzenie nowego anonimowego opakowania funkcji tymczasowej dla każdego wiersza. Czy jest inny sposób, aby to zrobić?
Joshua Pinter

@JoshuaPinter Sama technika nie jest problemem. Jeśli potrzebujesz tej samej funkcji wywołać 10000 razy, możesz po prostu zapisać opakowanie w zmiennej, aby utworzyć ją tylko raz. Jeśli chcesz przekazać 10000 różnych kontekstów, niewiele możesz zrobić. Uważaj na przedwczesną optymalizację: jak zawsze w przypadku wydajności, musisz zmierzyć, czy jest problem, czy nie. Dzisiejsze silniki JavaScript są bardzo wydajne i mogą optymalizować kod w zaskakujący sposób.
Ferdinand Beyer

@FerdinandBeyer Niesamowite, dzięki za cynk. Znajomy powiedział mi, że to zła praktyka i że powinieneś zamiast tego użyć this.myFunction = this.myFunction.bind(this)w swojej constructormetodzie. Ale, jak powiedziałeś, kiedy musisz przekazać do niego różne konteksty dla każdego z nich, na przykład wszystkie różne wiersze, które klikasz, aby otworzyć stronę szczegółów tego wiersza, nie można tego uniknąć.
Joshua Pinter

@FerdinandBeyer, powiedzmy, że myvar jest ciągiem i jest zmieniany między dwoma kolejnymi wywołaniami przekazania changeViewMode jako zamknięcia, ale changeViewMode zawsze otrzymuje pierwszą wartość myvar, chcę wywołać funkcję zamknięcia z inną wartością argumentu przypisaną do tej samej zmiennej myvar,
nmxprime

42

Użyj Function.prototype.bind(). Cytując MDN:

bind()Metoda tworzy nową funkcję, która, kiedy nazywa, ma swój thiszestaw słów kluczowych do podanej wartości z danej sekwencji argumentów poprzedzających każdy pod warunkiem, że nowa funkcja jest wywoływana.

Jest obsługiwany przez wszystkie główne przeglądarki, w tym IE9 +.

Twój kod powinien wyglądać następująco:

$(edit_link).click(changeViewMode.bind(null, myvar));

Uwaga dodatkowa: zakładam, że jesteś w kontekście globalnym, tj. thisZmienna jest window; w przeciwnym razie użyj thiszamiast null.


Dzięki, to mi pomogło. Użyłem tego w ten sposób:$.ajax(url).done(handler.bind(this, var1, var2));
Thomas

2
Która opcja jest najlepsza? Używasz zamknięcia lub funkcji bind? Daj mi znać, jeśli ma to jakiś wpływ na wydajność
Varun,

5
@Varun Zobacz Dlaczego
Michał Perłakowski

15

Nie, ale możesz przekazać jeden bez parametrów i zrobić to:

$(edit_link).click(
  function() { changeViewMode(myvar); }
);

Więc przekazujesz anonimową funkcję bez parametrów, która następnie wywołuje sparametryzowaną funkcję ze zmienną w zamknięciu



7

Lub jeśli używasz es6, powinieneś być w stanie użyć funkcji strzałki

$(edit_link).click(() => changeViewMode(myvar));

2

Możesz to zrobić

var message  = 'Hello World';

var callback = function(){
alert(this)
}.bind(message);

i wtedy

function activate(callback){
  callback && callback();
}

activate(callback);

Lub jeśli twój callback zawiera bardziej elastyczną logikę, możesz przekazać obiekt.

Próbny


2

Oto przykład zgodny z podejściem Ferdinanda Beyera:

function function1()
{
    function2(function () { function3("parameter value"); });
}
function function2(functionToBindOnClick)
{
    $(".myButton").click(functionToBindOnClick);
}
function function3(message) { alert(message); }

W tym przykładzie „wartość parametru” jest przekazywana z funkcji 1 do funkcji 3 poprzez funkcję 2 przy użyciu zawijania funkcji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.