Jak przekazać wartość (nie referencję) zmiennej JS do funkcji? [duplikat]

To pytanie ma już odpowiedź tutaj:

Oto uproszczona wersja czegoś, co próbuję uruchomić:

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
        change_selection(i);
    }); 
}

Ale uważam, że każdy słuchacz używa wartości wyników.length (wartość po zakończeniu pętli for). Jak Mogę dodać słuchaczy takich, że każdy używa wartości i w momencie dodawania go, a nie odniesienia do i?

Author: MD Sayem Ahmed, 2010-04-03

6 answers

W nowoczesnych przeglądarkach możesz użyć słów kluczowych let lub const, aby utworzyć zmienną o zasięgu blokowym:

for (let i = 0; i < results.length; i++) {
  let marker = results[i];
  google.maps.event.addListener(marker, 'click', () => change_selection(i));
}

W starszych przeglądarkach należy utworzyć osobny zakres, który zapisze zmienną w bieżącym stanie, przekazując ją jako parametr funkcji:

for (var i = 0; i < results.length; i++) {
  (function (i) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
      change_selection(i);
    }); 
  })(i);
}

Tworząc funkcję anonimową i wywołując ją ze zmienną jako pierwszym argumentem, przekazujesz wartość do funkcji i tworzysz zamknięcie.

 159
Author: Andy E,
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-07-06 10:27:04

Oprócz zamknięć, możesz użyć function.bind:

google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));

Przekazuje wartość i in jako argument do funkcji po wywołaniu. ({[4] } jest do wiązania this, którego w tym przypadku nie potrzebujesz.)

function.bind został wprowadzony przez Prototype framework i został ustandaryzowany w ECMAScript Fifth Edition. Dopóki wszystkie przeglądarki nie obsługują go natywnie, możesz dodać własne function.bind wsparcie za pomocą zamknięć:

if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}
 35
Author: bobince,
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
2010-04-02 22:19:35

Zamknięcia:

for (var i = 0, l= results.length; i < l; i++) {
    marker = results[i];
    (function(index){
        google.maps.event.addListener(marker, 'click', function() { 
            change_selection(index);
        }); 
    })(i);
}

EDIT, 2013: Są one obecnie powszechnie określane jako IIFE

 13
Author: David Murdoch,
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
2013-09-19 14:12:39

Kończysz z zamknięciem. Oto artykuł na temat zamknięć i jak z nimi pracować. Sprawdź przykład 5 na stronie; to scenariusz, z którym masz do czynienia.

EDIT: cztery lata później link nie działa. Głównym powodem powyższego problemu jest to, że pętla for tworzy zamknięcia(konkretnie na marker = results[i]). Ponieważ {[2] } jest przekazywane do addEventListener, widzisz efekt uboczny zamknięcia: współdzielone "środowisko" jest aktualizowane z każdą iteracją pętli, zanim w końcu zostanie "zapisany" poprzez zamknięcie Po ostatecznej iteracji. MDN wyjaśnia to bardzo dobrze.

 2
Author: ajm,
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
2014-12-22 21:12:45
for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', (function(i) {
        return function(){
            change_selection(i);
        }
    })(i)); 
}
 -2
Author: user3647947,
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
2014-05-17 15:45:58

Myślę, że możemy zdefiniować zmienną tymczasową do przechowywania wartości i.

for (var i = 0; i < results.length; i++) {
 var marker = results[i];
 var j = i;
 google.maps.event.addListener(marker, 'click', function() { 
   change_selection(j);
 }); 
}
Nie testowałem go jednak.
 -4
Author: Ken,
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-06-06 17:20:56