Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Добавление в эвент значение переменной (https://javascript.ru/forum/misc/72641-dobavlenie-v-ehvent-znachenie-peremennojj.html)

BOCbMOU 14.02.2018 00:58

Добавление в эвент значение переменной
 
Суть вопроса в следующем: можно ли как-то, при добавлении элементу эвента (через джс), передать в функцию непосредственно значение переменной, а не её название.

То есть у нас имеется следующее:
g.addEventListener("click", function () { faunaAdd(scale); });
g.onclick = function () { faunaAdd(scale); };

Вызов функции faunaAdd в которую надо передать значение scale, но проблема в том, что таким способом передаётся непосредственно само название переменной и в итоге при срабатывании эвента в функцию будет передано, по сути, ничего, ведь scale в эвенте не определён.

Я долго пытался найти решение этой проблемы гугле, но то ли плохо искал, то ли ещё что, но не нашёл вообще ничего. Единственное до чего допёр сам, это сделать объявление так:
g.setAttribute("onclick", "faunaAdd(" + scale + ");");

Тогда да, передаётся именно значение и всё работает как надо, но выглядит это... Ужасно и неудобно.
Собственно поэтому и возник вопрос, может кто знает как сделать подобное, но с нормальным объявлением.

j0hnik 14.02.2018 01:03

в корне неправильный подход.
во первых хорошим тоном считается не встраивать в html теги обработчики, а так чтобы вешать через setAttribute вижу впервые.

напишите что хотите сделать, подскажем как будет правильно.

BOCbMOU 14.02.2018 01:19

Цитата:

Сообщение от j0hnik (Сообщение 478071)
в корне неправильный подход.
во первых хорошим тоном считается не встраивать в html теги обработчики, а так чтобы вешать через setAttribute вижу впервые.

напишите что хотите сделать, подскажем как будет правильно.

В данном случае эвенты могу вешать только на g элементы, поскольку у меня svg поле с g элементами, в которых polygon и text.

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

Короче, если мы используем этот способ:
g.onclick = function () { faunaAdd(scale); };

то получаем следующий эвент:
function () { faunaAdd(scale); };

А если используем тот костыль, до которого я дошёл:
g.setAttribute("onclick", "faunaAdd(" + scale + ");");

то получаем на выходе следующее: ( scale = 0.3; )
function () { faunaAdd(0.3); };

И вот мне надо получить последнее, но нормальными путями, если это возможно, конечно же.

П.с.: ещё уточню, что это новый элемент:
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");

Aetae 14.02.2018 01:20

"Хуяк-хуяк" решения:
g.scale = scale;
g.addEventListener("click", faunaAdd); //внутри faunaAdd использовать this.scale
g.addEventListener("click", faunaAdd.bind(this, scale)); //заодно и перепривяжем this
g.addEventListener("click", function(scale){
  return function(){
    faunaAdd(scale);
  }
}(scale) ); //хардкор classic
...
А как делать нормально - зависит от конкретной ситуации.)

И да, в вашем случае не "передаётся имя, которого нет", а происходит где-то после изменение переменной.

BOCbMOU 14.02.2018 01:30

Цитата:

Сообщение от Aetae (Сообщение 478075)
g.addEventListener("click", function(scale){
  return function(){
    faunaAdd(scale);
  }
}(scale) ); //хардкор classic

Благодарствую, но можно уточнить для чего 2 и 5 строки? Я их смысл тут не улавливаю.

Aetae 14.02.2018 01:44

Магия.)

function(scale){...}(scale)
создаём анонимную функцию и тут же на месте её вызываем с параметром scale. Теперь есть отдельный внешний scale и есть отдельный scale как параметр функции.
return function(){ faunaAdd(scale);}
Создаём ещё одну анонимную функцию и возвращаем её как результат предыдущей. Это новосоданная функция замыкает на себя внутренний scale, к которому больше никто не имеет доступа кроме неё, после самовыполнения вышестоящей функции.
Т.о. в addEventListener попадет тот же самый
function(){ faunaAdd(scale); }
только scale в нём теперь отдельный.

Чтоб понятнее, можно записать так
function getFaunaAddWithScale(innerScale){
  return function(){
    faunaAdd(innerScale);
  }
}
var faunaAddWithScale = getFaunaAddWithScale(scale);

g.addEventListener("click", faunaAddWithScale );


Собсно тут работает тот же самый механизм замыканий, что и мешал вам. Только у вас замыкалась внешняя переменная, которая со временем менялась, а тут замыкается, так сказать, персональная, неизменная.)

BOCbMOU 14.02.2018 02:08

Aetae,
Спасибо, я понял, правда это объяснение было не очень понятно из-за одинакового названия переменной, вот так, имхо, понятнее:
g.addEventListener("click", function(a){
  return function(){
    faunaAdd(a);
  }
}(scale) ); //хардкор classic

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

Впрочем, вместо этого можно использовать этот вариант:
g.scale = scale;
g.addEventListener("click", faunaAdd.bind(this, scale));

Но я так понял лучше всё же тот что выше использовать?


Часовой пояс GMT +3, время: 16:45.