Переменная, используемая в качестве аргумента функции, изменяется, влияя на последующий вызов функции

Я понятия не имею, что происходит, я потратил бесчисленные часы на отладку своего кода, пока не нашел слабое место.

концепция

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) это звонки. Каждая из двух ссылок должна иметь разные вызовы функций. Я предлагаю использовать этот пустой сайт.

theCode.monkey.js

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 может быть перемещен в тело функции. Если они используются - обратите внимание, что порядок ключей объекта не гарантируется.

Другие вопросы по тегам