Как передать значение (а не ссылку) переменной JS в функцию? [дубликат]
этот вопрос уже есть ответ здесь:
вот упрощенная версия того, что я пытаюсь запустить:
for (var i = 0; i < results.length; i++) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
}
но я нахожу, что каждый слушатель использует значение результатов.длина (значение, когда цикл for прекращает.) Как я могу добавить слушателей таким образом, что каждый использует значение i в то время, когда я его добавляю, а не ссылку на i?
6 ответов:
В современных браузерах, вы можете использовать
let
илиconst
ключевые слова для создания переменной области блока:for (let i = 0; i < results.length; i++) { let marker = results[i]; google.maps.event.addListener(marker, 'click', () => change_selection(i)); }
в старых браузерах вам нужно создать отдельную область, которая сохраняет переменную в ее текущем состоянии, передавая ее в качестве параметра функции:
for (var i = 0; i < results.length; i++) { (function (i) { marker = results[i]; google.maps.event.addListener(marker, 'click', function() { change_selection(i); }); })(i); }
создавая анонимную функцию и вызывая ее с переменной в качестве первого аргумента, вы передаете значение функции и создаете закрытие.
а также закрытие, вы можете использовать
function.bind
:google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));
передает значение
i
в качестве аргумента функции при вызове. (null
для привязкиthis
, который вам не нужен в этом случае.)
function.bind
был представлен прототипом фреймворка и был стандартизирован в пятом издании ECMAScript. Пока браузеры все поддерживают его изначально, вы можете добавить свой собственныйfunction.bind
поддержка с помощью закрытия: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)) ); }; }; }
закрытие:
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: Теперь они обычно называются IIFE
вы заканчиваете с закрытием.
вот статья о закрытии и как с ними работать. Проверьте Пример 5 на странице; это сценарий, с которым вы работаете.EDIT: четыре года спустя эта ссылка мертва. Корень проблемы выше заключается в том, что
for
петля образует замыкания (в частности, наmarker = results[i]
). Какmarker
переходит вaddEventListener
, вы видите побочный эффект закрытия: общая "среда" обновляется с каждой итерацией цикла, прежде чем он будет окончательно "сохранен" через закрытие после окончательной итерации. MDN объясняет это очень хорошо.