Javascript, захват переменной
От: ezdoctor  
Дата: 22.12.17 18:03
Оценка:
Добрый день,
В Javascript все переменные статические и определены в scope функции, это я знаю. Также знаю, что для захвата локальной переменной (в том ее состоянии, что есть сейчас) можно определить новую функцию, в ней скопировать переменную, тем самым создав новую переменную в другом scope. Тем не менее, пока не получается найти изящного решения практической проблемы.

Итак, в некой JS функции я прохожусь по циклу и динамически создаю элементы, по одному на итерацию. Например:
for (i = 0; i < 10; ++i) {
var element = createMyElement(); // Тут создаем новый HTML элемент, например, <div>.
element.innerHTML = "<span onclick='func(i)'>some text</span>";
}

По описанным выше причинам при клике на любой элемент будет вызван func(10). Такой простой случай легко фиксится заменой строчки на: "<span onclick='func(" + i + ")'>some text</span>".
Гораздо сложнее, если нам надо передать в функцию не число, а какой-то объект:
for (i = 0; i < 10; ++i) {
var element = createMyElement();
var obj = getMyObject(i); // Тут получаем некий объект сложной природы.
element.innerHTML = "<span onclick='func(obj)'>some text</span>";
}
Опять же при клике на любой из наших элементов вызывается функция от последнего полученного объекта, и ничего удивительного в этом нет.

Вижу некрасивый вариант:
var objects = [];
for (i = 0; i < 10; ++i) {
var element = createMyElement();
var obj = getMyObject(i);
objects.push(obj);
element.innerHTML = "<span onclick='func2(objects, " + i + ")'>some text</span>";
}
где func2 получает список объектов и индекс, по индексу получает нужный. Некрасиво.

Есть идеи, как правильно при создании элемента (вернее даже при создании его внутреннего HTML) связать обработчик события с конкретным текущим значением переменной obj?
Re: Javascript, захват переменной
От: AntoxaM  
Дата: 22.12.17 18:29
Оценка:
Здравствуйте, ezdoctor, Вы писали:

E>Добрый день,

E>В Javascript все переменные статические и определены в scope функции, это я знаю. Также знаю, что для захвата локальной переменной (в том ее состоянии, что есть сейчас) можно определить новую функцию, в ней скопировать переменную, тем самым создав новую переменную в другом scope. Тем не менее, пока не получается найти изящного решения практической проблемы.
...
E>Есть идеи, как правильно при создании элемента (вернее даже при создании его внутреннего HTML) связать обработчик события с конкретным текущим значением переменной obj?
Стандартно: либо через let, либо вложенную функцию.
Поподробнее, например, здесь: https://github.com/azat-io/you-dont-know-js-ru/blob/master/scope%20%26%20closures/ch5.md
Re: Javascript, захват переменной
От: John1979  
Дата: 22.12.17 22:47
Оценка: +2
Здравствуйте, ezdoctor, Вы писали:

E>По описанным выше причинам при клике на любой элемент будет вызван func(10). Такой простой случай легко фиксится заменой строчки на: "<span onclick='func(" + i + ")'>some text</span>".

E>Гораздо сложнее, если нам надо передать в функцию не число, а какой-то объект:
E>for (i = 0; i < 10; ++i) {
E> var element = createMyElement();
E> var obj = getMyObject(i); // Тут получаем некий объект сложной природы.
var span = document.createElement('span')
span.onclick = func.bind(null, obj)
span.innerText = 'some text'
element.appendChild(span)
E>}
E>Опять же при клике на любой из наших элементов вызывается функция от последнего полученного объекта, и ничего удивительного в этом нет.
Re: Javascript, захват переменной
От: ssmaslov  
Дата: 25.12.17 07:12
Оценка:
Здравствуйте, ezdoctor, Вы писали:

E>Добрый день,

E>В Javascript все переменные статические и определены в scope функции, это я знаю. Также знаю, что для захвата локальной переменной (в том ее состоянии, что есть сейчас) можно определить новую функцию, в ней скопировать переменную, тем самым создав новую переменную в другом scope. Тем не менее, пока не получается найти изящного решения практической проблемы.

E>Итак, в некой JS функции я прохожусь по циклу и динамически создаю элементы, по одному на итерацию. Например:

E>for (i = 0; i < 10; ++i) {
E> var element = createMyElement(); // Тут создаем новый HTML элемент, например, <div>.
E> element.innerHTML = "<span onclick='func(i)'>some text</span>";
E>}

E>По описанным выше причинам при клике на любой элемент будет вызван func(10). Такой простой случай легко фиксится заменой строчки на: "<span onclick='func(" + i + ")'>some text</span>".

E>Гораздо сложнее, если нам надо передать в функцию не число, а какой-то объект:
E>for (i = 0; i < 10; ++i) {
E> var element = createMyElement();
E> var obj = getMyObject(i); // Тут получаем некий объект сложной природы.
E> element.innerHTML = "<span onclick='func(obj)'>some text</span>";
E>}
E>Опять же при клике на любой из наших элементов вызывается функция от последнего полученного объекта, и ничего удивительного в этом нет.

E>Вижу некрасивый вариант:

E>var objects = [];
E>for (i = 0; i < 10; ++i) {
E> var element = createMyElement();
E> var obj = getMyObject(i);
E> objects.push(obj);
E> element.innerHTML = "<span onclick='func2(objects, " + i + ")'>some text</span>";
E>}
E>где func2 получает список объектов и индекс, по индексу получает нужный. Некрасиво.

E>Есть идеи, как правильно при создании элемента (вернее даже при создании его внутреннего HTML) связать обработчик события с конкретным текущим значением переменной obj?


function func1(i) {
var obj = getMyObject(i);
func2(obj);
}

for (var i = 0; i < 10; ++i) {
var element = createMyElement();
element.innerHTML = "<span onclick='func1(' + i + ')'>some text</span>";
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.