Переменная, используемая в качестве аргумента функции, изменяется, влияя на последующий вызов функции
Я понятия не имею, что происходит, я потратил бесчисленные часы на отладку своего кода, пока не нашел слабое место.
концепция
function fnc() {
var hl = { // hl stands for hyperlink (<a>)
uid : ["player.id", "uid"],
inVal : ["infra.value*", "infrastructure_value"]
}
for (key in hl) { .. do the code in block 1 at bottom .. }
}
Код должен пройти через массив (объект) значений, состоящий из id : [text, call]
и связать click(fnc(call))
событие в <a>text</a>
с учетом id
, (При нажатии на ссылку запускается та же функция - это желательно.)
Код
Это код вкратце:
fnc = function(sort_by, direction) {
var qswitch = 1;
if (qswitch == 1) {
key = "uid"; console.log("#"+key); // #uid
$("#"+key).unbind("click").click( function() { fnc(hl[key][1], direction); });
console.log(key); // uid
key = "inVal"; console.log("#"+key); // #inVal
$("#"+key).unbind("click").click( function() { fnc(hl[key][1], direction); });
console.log(key); // inVal
}
if (qswitch == 2) {
$("#uid").unbind("click").click( function() { fnc(hl["uid"][1], direction); });
$("#inVal").unbind("click").click( function() { fnc(hl["inVal"][1], direction); });
}
}
Эта проблема
Вы можете увидеть два блока одного и того же кода. Первая должна работать динамически, как описано выше, но обе ссылки ссылаются на один и тот же вызов функции. (<-это ошибка) Привязка событий без использования переменной работает просто отлично, и каждая ссылка запускает свою собственную function(parameters)
,
Это ошибка?
... или я просто тупой и перегруженный работой?
Установите пользовательский скрипт tampermonkey, зайдите на любой сайт, откройте консоль (F12) и посмотрите вывод. Всякий раз, когда вы нажимаете на ссылку, он пишет, что function(parameters)
это звонки. Каждая из двух ссылок должна иметь разные вызовы функций. Я предлагаю использовать этот пустой сайт.
1 ответ
key = "uid"; console.log("#"+key); // #uid
$("#"+key).unbind("click").click( function() { fnc(hl[key][1], direction); });
console.log(key); // uid
key = "inVal"; console.log("#"+key); // #inVal
$("#"+key).unbind("click").click( function() { fnc(hl[key][2], direction); });
console.log(key); // inVal
Проблема здесь в том, что key
перезаписывается вторым присваиванием перед его использованием в первом обратном вызове. Обратные вызовы событий не вызываются в то же время, что и их определяющая функция, и их определяющая функция не ожидает их запуска. Самым простым решением было бы использовать две отдельные переменные, но, похоже, я смотрю на развернутый цикл, и ваш код на самом деле выглядит так:
for(var key in hl){
//compute i
key = "inVal"; console.log("#"+key); // #inVal
$("#"+key).unbind("click").click( function() { fnc(hl[key][i], direction); });
console.log(key); // inVal
}
(если var
отсутствует, вы должны добавить его - необъявленные переменные находятся в глобальной области видимости. Вы не хотите их там. В строгом режиме они терпят неудачу полностью) (не уверен, где i
исходит из, но давайте предположим, что он генерируется в каждом цикле до того, как он увиден) вы можете использовать выражение, вызванное сразу же из функции (IIFE), чтобы записать значение в новую переменную в новой области (помните, javascript использует области действия функции):
for(var key in hl){
// compute `i`
(function(key, i){
key = "inVal"; console.log("#"+key); // #inVal
$("#"+key).unbind("click").click( function() { fnc(hl[key][i], direction); });
console.log(key); // inVal
})(key,i)
}
сейчас key
а также i
внутри цикла ссылаются на аргументы IIFE, а не на постоянно меняющиеся переменные переменные, объявленные вне цикла.
Также обратите внимание, что: если предыдущие значения i
не используются для генерации новых, то вычисление i
может быть перемещен в тело функции. Если они используются - обратите внимание, что порядок ключей объекта не гарантируется.