Как заставить этот код работать?

Код дает мне: A B C

Когда я нажимаю на ABC, он всегда показывает последнюю "водку". Я хочу, чтобы "Мартин" (для A), "Линдсей" (для B), "Водка" (для C)
Пожалуйста, помогите мне на моем примере.

myArray = [
    {
        letter: "A",
        brand: "martin"
    },
    {
        letter: "B",
        brand: "lindsay"
    },
    {
        letter: "C",
        brand: "vodka"
    }
];
    var list = '';
    for (var i = 0; i < myArray.length; i++) {
    list += "<br>" + myArray[i].letter;

    new_info = myArray[i].link;
    (function(new_info) {
         $(this).click(function(){        //this - refers to A or B or C
                 $('#box2').text(new_info);
                 });
    }).call(this, myArray[i])
}

$('#box1').append(list);

1 ответ

Решение

Редактировать:
Я сказал, что не собираюсь писать ваш код для вас... ну, я сделал: эта скрипка делает именно то, что вы ищете. Я решил проблему с контекстом (this), вопросы закрытия и подразумеваемые глобалы. Надо еще много работы, но скрипка показывает, что все говорили: $(this) не имеет, не может и никогда не будет указывать на строковую константу, такую ​​как"A", or "B",

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

function()
{
    $('#box2').text(new_info);
}

куда new_info переменная, которая объявлена ​​в более высокой области видимости Все идет нормально. Проблема в том, что создаваемый объект функции не имеет собственной копии какого-либо значения этой переменной (new_info) произошло, когда эта функция была создана. Вместо этого функция ссылается на эту переменную. Поэтому, когда любая из этих функций вызывается $('#box2').text(new_info) будет решен в $('#box2').text("whatever value new_info holds when function is called")не $('#box2').text("whatever value new_info was holding when function was created"), Вы можете предоставить каждому обратному вызову доступ к копии, просто добавив в свой код вторую функцию:

$(this).click((function(currentNewInfo)
{
    return function()
    {
        $('#box2').text(currentNewInfo);
    }
}(new_info)));

Здесь я создаю функцию, которая принимает аргумент и вызывает его немедленно. я пас new_info в качестве аргумента, поэтому значение currentNewInfo будет что new_info держит в то время (ака копия)
Вызванная мною функция (IIFE - или выражение немедленно вызванной функции) возвращает фактический обратный вызов. В этом обратном вызове я не упоминаю new_info, но аргумент IIFE: currentNewInfo,

Поскольку каждая функция имеет свою область видимости, эта переменная заключена (отсюда и закрытие имени) и не может быть доступна или изменена извне. Единственное, что еще может получить доступ к currentNewInfo Переменная - это функция, возвращаемая IIFE.
Возможно, вас беспокоит конфликт имен (каждый созданный вами обратный вызов использует ссылки currentNewInfo), но это не так: каждый обратный вызов был создан отдельной функцией и, следовательно, имеет доступ к другой области. Невозможно иметь конфликт имен между областями, которые не имеют доступа друг к другу... Просто чтобы сделать вещи действительно простыми для понимания:

Что делает закрытие

Where  /\            and      /\
       ||                     ||
  is return function()      is scope of IIFE

Таким образом, замыкания имеют доступ к области действия функции после ее возврата. Эта область имеет приоритет при разрешении выражения в значение. Чтобы лучше это понять, вот похожая диаграмма, показывающая, как JS разрешает выражения:

JS и объемное сканирование
Где каждая розовая "запись внешней среды" - это область действия функции (область закрытия функции, которая уже вернулась, или функция, которая вызывается в данный момент). Последнее окружение будет либо глобальным объектом, либо нулевым (в строгом режиме). Это все, что нужно сделать.

Честно говоря, затворы сложно сначала обдумать, но как только вы поймете, что я пытался объяснить здесь, это будет очень весело.
Пройдя по этой ссылке, я могу перейти к описанию вариантов использования и преимуществ, а также способов работы вложенных замыканий, но в итоге я бы написал книгу. Ссылка, которую я разместил, отлично объясняет, как работают замыкания, используя довольно глупые рисунки. Это может показаться детским, но на самом деле они мне очень помогли, когда я пытался понять концепцию лямбда-функций, замыканий и областей действия вне вызова функции. Диаграммы выше взяты со страницы, на которую я ссылаюсь, которая объясняет концепции немного более подробно, но я все еще думаю, что простые, грубые рисунки довольно понятны.

Другие вопросы:
Как кто-то указал: "Чего вы ожидаете? thisдля ссылки ". Глядя на фрагмент, this будет просто ссылаться на глобальный объект (window), прикрепляя такой же / похожий обработчик событий к windowпросто не имеет смысла, если вы спросите меня.
Глобальные переменные являются злом, аглобальные переменные - тем более. Я не вижу new_infoни myArray быть объявленным где угодно Способ, с помощью которого JS разрешает выражения, весьма неудачен и откатывается на создание глобальных переменных без какого-либо взгляда:

var bar = 666;//global, always evil
function createGlobal()
{
    var local = 2;
    foo = bar * local;
}
createGlobal();

Давайте посмотрим на foo:

JS is in createGlobal scope: var local is declared, and assigned 2.
   foo is used, and assigned bar*local
    ||                       ||   \\=>found in current scope, resolves to 2
    ||                       ||
    ||                       \\=>found in global scope, resolves to 666
    ||
    ||
    ||=> JS looks for foo declaration in function scope first, not found
    ||
    ||=> moves up 1 scope (either higher function, or global scope)
    ||
    \\=>Global scope, foo not found, create foo globally! - hence, implied global
             \\
              \\=>foo can now be resolved to global variable, value undefined

Чрезмерные запросы DOM: все ваши обратные вызовы обработчика событий выглядят так:

$('#box2').text(new_info);

Это ($('#box2')) на самом деле так же, как написание document.getElementById('#box2'), Который практически английский. Думайте об этом так: каждый раз, когда клиент нажимает на $(this) - что бы это ни было, вы обращаетесь к DOM и сканируете его на предмет с заданным идентификатором. Почему бы не сделать это один раз и использовать ссылку, хранящуюся в памяти, чтобы изменить текст. Это сохраняет бесчисленные запросы DOM. Вы можете использовать переменную или (в свете того, что я объяснил о замыканиях) замыкание:

var list = (function(box2, list, i)
{//list & i are arguments, so local to scope, too
    for (i = 0; i < myArray.length; i++)
    {
        list += "<br>" + myArray[i].letter;//<-- don't know why you use this
        //new_info = myArray[i].link; no need for this var
        $(this).click((function(new_info)
        {//new_info is closure var now
            return function ()
            {//box2 references DOM element, is kept in memory to reduce DOM querying
                box2.text(link);
            };
        }(myArray[i].link));//instead of new_info, just pass value here
    }
    return list;//return string, assign to outer variable
}($('#box2'), ''));//query dom here, pass reference as argument
Другие вопросы по тегам