Вопрос о переменной области JavaScript - PullRequest
5 голосов
/ 17 сентября 2010

У меня проблемы с разрешением области видимости с помощью моего JavaScript. У меня есть массив dog [], определенный из JSON, к которому мне нужен доступ из вложенной функции.

function blah(json) {
 for (var u = 0; u < json[0][1][u].length; u ++ ) {
    var dog = 'k' + json[0][1][u].doggies;
    console.log(dog); // prints array of doggie strings
    $('#puppy').click(function(dog) {    // dog is passed in the function
       console.log(dog); // Syntax error, unrecognized expression: #[object Object]
       $('#' + dog).css('display, 'none');
     });
   }
 }

когда я не передаю собаку в функцию щелчка: я получаю:

 $('#puppy').click(function() {
  console.log(dog) // (12)  main.js:122k4c812e3a7275e10331000000 - this is the last value in the array - from safari console
  $('#' dog).css('display', 'none);
   }

У кого-нибудь есть предложения получить массив с каждым элементом, переданным в функцию click? Или я вызываю метод css неправильно, чтобы скрыть эти div?

Ответы [ 4 ]

4 голосов
/ 17 сентября 2010

Задача 1

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

Возьмите этот код, например:

function foo() {
    var i, func;

    for (i = 0; i < 10; ++i) {
        if (i == 0) {
            func = function () {
                alert(i);
            }
        }
    }

    func();
}

foo();

Вы можете ожидать foo, чтобы 0 был предупрежден.Однако значение i изменилось с момента создания функции, назначенной func;вызов func предупреждает «10».

Вот еще один пример, иллюстрирующий концепцию:

function foo() {
    var i = 42;

    function func() {
        alert(i);
    }

    for (i = 0; i < 10; ++i) {
        // do nothing
    }

    func();
}

foo();

Попробуйте выяснить, что будет предупреждено, и запустите код в качестве теста.

Задача 2

Вторая проблема заключается в том, что переменные связаны с областью действия функции (а не с областью блока, как вы ожидаете).

Возьмите этот код:

function foo() {
    var i;

    for (i = 0; i < 10; ++i) {
        var j = i;
    }

    alert(j);
}

foo();

Вы можете ожидать, что этот код выдаст предупреждение «undefined», выдаст ошибку времени выполнения или даже выдаст ошибку синтаксиса.Тем не менее, «10» предупрежден.Зачем?В JavaScript приведенный выше код эффективно транслируется:

function foo() {
    var i;

    var j;

    for (i = 0; i < 10; ++i) {
        j = i;
    }

    alert(j);
}

foo();

Из этого примера должно быть более ясно, что «10» действительно предупрежден.

Решение

Итаккак вы решаете свою проблему?Самый простой способ - изменить свою логику: вместо того, чтобы прикреплять один обработчик событий на собаку, атакуйте одного обработчика событий на коллекцию собак.Например:

function blah(json) {
    $('#puppy').click(function () {
        var u, dog;

        for (u = 0; u < json[0][1][u].length; u++) {
            dog = 'k' + json[0][1][u].doggies;

            console.log(dog);

            $('#' + dog).css('display', 'none');
        }
    });
}

Если вас интересует «правильное» преобразование существующего кода (т. Е. Такое же поведение, за исключением исправленной ошибки), я могу привести пример этого какЧто ж.Однако решение, которое я дал выше, является намного лучшим решением и приводит к более чистому коду.

2 голосов
/ 17 сентября 2010

Важное примечание:

Вы забыли закрыть свою цитату. Это:

$('#' + dog).css('display, 'none');

Должно быть:

$('#' + dog).css('display', 'none');

Улучшенный цикл:

Есть несколько проблем с вашим скриптом. Я сосредоточусь на общей логической структуре цикла.

Вместо того, чтобы прикреплять множество обработчиков к .click(), просто присоедините один обработчик, который выполняет итерации по JSON, используя jQuery .each(). Первый аргумент обратного вызова .each() - это номер индекса, а второй аргумент - это значение. Вы можете использовать эти 2, называя аргументы или используя arguments[0] и arguments[1]. Я показываю прежний метод ниже:

Я добавил еще несколько тестовых выводов для демонстрационных целей:

function blah(json) {
     $('#puppy').click(function() { 

          // iterate over each json[0][1]
        $.each(json[0][1], function(index, value) {

              // Your original 2 lines
            console.log(value);
            $('#' + value).css('display', 'none');

              // This is just test output, so you can see what is going
              // on.
            $("body").append("Number " + index + " is " + value ".<br/>");
        });
     });
}     
1 голос
/ 17 сентября 2010

Почему бы просто не дать собакам класс .dog и скрыть их при нажатии #puppy?

$("#puppy").click(function() {
    $(".dog").hide();
});

Или, так как идентификаторы вашей собаки, кажется, начинаются с k, вы могли бы рассмотрим что-то вроде этого:

$("#puppy").click(function() {

    // hide everything with ID beginning with 'k'
    $('[id^=k]').hide();
});
0 голосов
/ 17 сентября 2010

Вы не можете передать значение собаки в событие jquery click, как вы это сделали.Подпись функции щелчка:

$(object).click(function(){


});

Вы не можете передать собаку таким образом.Даже если функция ожидает параметр, его имя может вызвать проблемы.Возможно, вам придется хранить значения dog в более глобальной области видимости, чтобы при возникновении события щелчка у вас все еще был доступ к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...