Как вызвать функцию с правильным аргументом в объекте jQuery-resizable, который создается в цикле?

У меня есть пара объектов с изменяемыми размерами, и я хотел бы вызвать функцию 'changeS()', когда я прекращаю изменять размер объекта.
Функция changeS () должна принимать в качестве первого аргумента имя объекта, для которого она вызывается.
Я имею в виду:
когда я прекращаю изменять размер объекта "#resizable0", тогда должен называться changeS(#resizable0,new_size - old_size),
когда я прекращаю изменять размер объекта "#resizable1", тогда должен вызываться changeS(#resizable1,new_size - old_size) и т. д.

Когда я просто устанавливаю в коде этот метод для каждого имеющегося у меня объекта, все в порядке, но я бы хотел сделать это в цикле for(), потому что объектов будет намного больше, и тогда у меня возникнет проблема:

var old_size=0;
var new_size=0;
var x,i;

for(i=0; i<5; i++){
x = "#resizable"+i;
var $res = $(x);

$res.resizable({
    grid: 22, minHeight:22, handles: 's',
    start: function(event,ui) {
        old_size = ui.originalSize.height;
    },
    stop: function(event,ui) {
        new_size = ui.size.height;

        if(new_size!=old_size)
            changeS($res,new_size - old_size);
    }
});
}

Я не знаю, как правильно передать имя объекта в качестве аргумента функции.
Когда функция changeS () выполняется, она всегда вызывается с тем же именем - именем последнего созданного объекта (в данном случае "#resizable5").

Мой вопрос:
Как сделать так, чтобы для каждого объекта была вызвана функция changeS () с соответствующим аргументом (именем этого объекта)?

Спасибо, попКонр

1 ответ

Решение

Функции, которые вы создаете в цикле, являются замыканиями. Они сохраняют постоянную ссылку на переменные, которые они закрывают, а не копию значения на момент определения функции. И поэтому все они видят последнее значение, которое вы назначаете $res, а не значение во время "их" цикла.

Обычный способ решить эту проблему - использовать фабричную функцию, что-то вроде этого:

var x,i;

for(i=0; i<5; i++){
    x = "#resizable"+i;
    var $res = $(x);

    makeResizeable($res);
}

function makeResizeable($thisres) {
    var old_size = 0,
        new_size = 0;

    $thisres.resizable({
        grid: 22, minHeight:22, handles: 's',
        start: function(event,ui) {
            old_size = ui.originalSize.height;
        },
        stop: function(event,ui) {
            new_size = ui.size.height;

            if(new_size!=old_size)
                changeS($thisres,new_size - old_size);
        }
    });
}

Обратите внимание, как мы сейчас используем $thisresаргумент передается в фабричную функцию makeResizeable, скорее, чем $res, поскольку аргумент заполняется в функции, которые мы создаем в makeResizeable не изменился Также обратите внимание, что я переехал new_size а также old_size в эту фабричную функцию, а также. Обработчики событий закроют эти данные, и каждая пара получит свои собственные копии этих переменных.

Замыкания не сложны, но есть несколько фундаментальных вещей, которые люди обычно неправильно понимают. Однако, как только вы их опустите, вы будете в хорошей форме.

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