Ситуация в чем-то похожа -
var someVar = some_other_function();
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
Проблема в том, что значение someVar не отображается внутри функции прослушивателя addEventListener, где оно, вероятно, обрабатывается как новая переменная.
Не самый чистый способ, но работает. Обратите внимание, что если someVar может быть только цифрой или текстом: eval ('someObj.addEventListener ("щелчок", function () {some_funct ion (' + someVar + ');}); ');
Только что возникла эта проблема сегодня - решение, приведенное здесь, правильное (у других решений есть проблемы, такие как проблема с петлей и т. д.) - stackoverflow.com/a/54731362/984471



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В написанном вами коде нет абсолютно ничего плохого. И some_function, и someVar должны быть доступны, если они были доступны в контексте, когда анонимный
function() { some_function(someVar); }
был создан.
Убедитесь, что предупреждение дает вам значение, которое вы искали, убедитесь, что оно будет доступно в рамках анонимной функции (если у вас нет другого кода, который работает с той же переменной someVar рядом с вызовом addEventListener)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
Это не работает в цикле for. Я всегда получаю последнее значение, а не то, которое принадлежало этой итерации. Любое решение?
Кто-нибудь знает, почему это не работает в цикле? В чем причина такого поведения?
@Morfidon, потому что функция с глобальными переменными действует как закрытие в javascript, что означает, что они запоминают среду за пределами своей лексической области. Если вы просто создаете разные функции в одной среде, они будут ссылаться на одну и ту же среду.
@Morfidon: в цикле значение someVar - это не то значение, которое оно имело при добавлении слушателя, а значение, которое оно имеет при выполнении слушателя. Когда слушатель выполняется, цикл уже завершился, поэтому значением someVar будет значение, которое оно имело при завершении цикла.
Это неправильный ответ, потому что он не позволяет нам использовать функцию removeEventListener после.
@ ankitbug94 Как можно было поместить someVar в Lexical scope, чтобы текущее значение можно было использовать внутри события? jQuery решает проблему с помощью event.dataapi.jquery.com/event.data, но как это сделать без jQuery?
@iMatoria Я только что обнаружил, что создание bound function с использованием метода .bind() решит проблему с циклами developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
@ LukeTO'Brien Извините за такую задержку с ответом. Если вы все еще хотите знать, вы всегда можете использовать частичные функции с использованием каррирования, который создает и возвращает новую функцию с их собственной лексической областью видимости. Вы можете найти это чрезвычайно полезным stackoverflow.com/questions/750486/…
@Morfidon см. Мой ответ ниже о том, что работает с циклами.
@NeonWarge: Пожалуйста, сравните профили перед таким жестким советом. Если вы эксперт в области SEO, вы должны знать, что ссылки становятся мертвыми, и посторонний не контролирует это. Вежливым способом можно было сообщить о неработающей ссылке и / или предложить исправление.
когда он входит в some_function, someVar может уже не иметь ничего, ссылающегося на себя, и уже был очищен в кадре стека вызовов.
Что, если слушатель зарегистрирован в функции mycustom, а обратный вызов должен повторно использовать некоторую переменную из функции mycustom ПЛЮС Я хочу сделать обратный вызов как глобальную функцию customHandler вместо функции анонимного обратного вызова? Как передать переменную из функции mycustom в глобальную функцию customHandler?
Значение someVar должно быть доступно только в контексте some_function(), а не от слушателя.
Если вы хотите, чтобы это было внутри слушателя, вы должны сделать что-то вроде:
someObj.addEventListener("click",
function(){
var newVar = someVar;
some_function(someVar);
},
false);
и используйте вместо него newVar.
Другой способ - вернуть значение someVar из some_function() для дальнейшего использования в слушателе (как новая локальная переменная):
var someVar = some_function(someVar);
Вы можете добавлять и удалять прослушиватели событий с аргументами, объявив функцию как переменную.
myaudio.addEventListener('ended',funcName=function(){newSrc(myaudio)},false);
newSrc - это метод с параметром myaudio в качестве параметра
funcName - это переменная имени функции
Вы можете удалить слушателя с помощью
myaudio.removeEventListener('ended',func,false);
Также попробуйте эти (IE8 + Chrome. Я не знаю для FF):
function addEvent(obj, type, fn) {
eval('obj.on'+type+'=fn');
}
function removeEvent(obj, type) {
eval('obj.on'+type+'=null');
}
// Use :
function someFunction (someArg) {alert(someArg);}
var object=document.getElementById('somObject_id') ;
var someArg = "Hi there !";
var func=function(){someFunction (someArg)};
// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive
Надеюсь, опечаток нет :-)
Насколько сложно было бы дать исчерпывающий ответ? Стоит ли мне тестировать это на FF? Ну, я не буду беспокоиться ...
Использовать
el.addEventListener('click',
function(){
// this will give you the id value
alert(this.id);
},
false);
И если вы хотите передать любое пользовательское значение в эту анонимную функцию, самый простой способ сделать это -
// this will dynamically create property a property
// you can create anything like el.<your variable>
el.myvalue = "hello world";
el.addEventListener('click',
function(){
//this will show you the myvalue
alert(el.myvalue);
// this will give you the id value
alert(this.id);
},
false);
Отлично работает в моем проекте. Надеюсь, это поможет
Да, определенно помогло, так как оно также сохранило ожидаемый объем в цикле for.
Почему бы просто не получить аргументы из целевого атрибута события?
Пример:
const someInput = document.querySelector('button');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)
{
window.alert(evt.currentTarget.myParam);
}<button class = "input">Show parameter</button>Помните, что JavaScript - это язык, ориентированный на прототипы!
Это правильный ответ, потому что он позволяет использовать после функции removeEventListener.
Разве это не должно быть evt.currentTarget.myParam? Если внутри someInput есть другой элемент, evt.target может относиться к внутреннему элементу. (jsfiddle.net/qp5zguay/1)
Это сохраняет this! Использование этого метода в машинописном тексте требует, чтобы элемент был any или же создавал подтип.
someInput.setAttribute («класс», «демокласс»);
Мои переменные продолжают возвращаться как неопределенные ... есть мысли о том, как это исправить?
Это правильный ответ, и это даже метод, который jQuery использует для передачи аргументов. За исключением того, что они хранят его в evt.data.myParam, но достаточно близко.
Если addEventListener предназначен для document, evt.target.myParam у меня не работал. Вместо этого мне пришлось использовать evt.currentTarget.myParam.
гораздо более элегантное решение.
Это старый вопрос, но я подумал, что предлагаю альтернативу с использованием ES5 .bind() - для потомков. :)
function some_func(otherFunc, ev) {
// magic happens
}
someObj.addEventListener("click", some_func.bind(null, some_other_func), false);
Просто имейте в виду, что вам нужно настроить свою функцию прослушивателя с первым параметром в качестве аргумента, который вы передаете в bind (ваша другая функция), а второй параметр теперь является событием (вместо первого, как это было бы) .
Посмотрите плюсы и минусы IIFE против bind ().
Используя Function.prototype.bind(), вы не можете удалить прослушиватель событий, лучше вместо этого использовать функцию каррирования (см. Ответ @ tomcek112)
ПРИМЕЧАНИЕ. some_other_func - это переменная, вы можете передать в some_func любое значение.
Function.prototype.bind () - это способ привязать целевую функцию к определенной области и дополнительно определить объект this в целевой функции.
someObj.addEventListener("click", some_function.bind(this), false);
Или захватить часть лексической области видимости, например, в цикле:
someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);
Наконец, если параметр this не нужен в целевой функции:
someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);
Вы можете просто связать все необходимые аргументы с помощью bind:
root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));
Таким образом, вы всегда будете получать event, arg1 и другие вещи, передаваемые в myPrettyHandler.
http://passy.svbtle.com/partial-application-in-javascript-using-bind
Спасибо! Уже пробовал .bind(), но без нуля в качестве первого параметра. что не сработало.
нет необходимости в null, он отлично работает с .bind(event, arg1), по крайней мере, с VueJS.
Другая альтернатива, возможно, не такая элегантная, как использование bind, но она действительна для событий в цикле.
for (var key in catalog){
document.getElementById(key).my_id = key
document.getElementById(key).addEventListener('click', function(e) {
editorContent.loadCatalogEntry(e.srcElement.my_id)
}, false);
}
Он был протестирован для расширений Google Chrome, и, возможно, e.srcElement необходимо заменить на e.source в других браузерах.
Я нашел это решение, используя комментарий, опубликованный Иматория, но я не могу отметить его как полезный, потому что у меня недостаточно репутации: D
Следующий ответ верен, но приведенный ниже код не работает в IE8, если предположим, что вы сжали файл js с помощью yuicompressor. (Фактически, все еще большинство людей в США используют IE8)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
function(){
some_function(someVar);
},
false);
Итак, мы можем исправить указанную выше проблему следующим образом, и она отлично работает во всех браузерах.
var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);
Надеюсь, это будет полезно для тех, кто сжимает файл js в производственной среде.
Удачи!!
Внутри всех функций есть специальная переменная: аргументы. Вы можете передать свои параметры как анонимные параметры и получить к ним доступ (по порядку) через переменную аргументы.
Пример:
var someVar = some_other_function();
someObj.addEventListener("click", function(someVar){
some_function(arguments[0]);
}, false);
Хм ... В чем причина отрицательного голоса? Если это было не то, что вы искали, пожалуйста, более четко объясните, что вы имеете в виду (я знаю, что на этот вопрос уже дан ответ). Но разве мой код не отвечает на то, о чем вы просили? Специальная переменная «arguments» дает вам доступ ко всем параметрам внутри функции.
Вот еще один способ (он работает внутри циклов):
var someVar = some_other_function();
someObj.addEventListener("click",
function(theVar){
return function(){some_function(theVar)};
}(someVar),
false);
Это лучший способ. Уродливо, но эффективно внутри циклов, поскольку отправка аргумента в анонимную функцию захватит переменную.
Следующий код отлично работал у меня (firefox):
for (var i=0; i<3; i++) {
element = new ... // create your element
element.counter = i;
element.addEventListener('click', function(e){
console.info(this.counter);
... // another code with this element
}, false);
}
Выход:
0
1
2
Что это вообще такое?
Отправка аргументов функции обратного вызова eventListener требует создания изолированной функции и передачи аргументов этой изолированной функции.
Вот небольшая полезная вспомогательная функция, которую вы можете использовать. На основе приведенного выше примера "привет, мир".)
Также необходимо поддерживать ссылку на функцию, чтобы мы могли аккуратно удалить слушателя.
// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running
// within loops.
//
// The anonymous function returns a closure, that will be executed when
// the event triggers. And since the arguments were captured, any vars
// that were sent in will be unique to the function.
function addListenerWithArgs(elem, evt, func, vars){
var f = function(ff, vv){
return (function (){
ff(vv);
});
}(func, vars);
elem.addEventListener(evt, f);
return f;
}
// Usage:
function doSomething(withThis){
console.info("withThis", withThis);
}
// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");
// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);
Это ответ от 15 года, но это именно то, что мне нужно для решения этой проблемы с помощью хука useRef. Если вы используете перехватчик ref и вам нужен слушатель для него, который вы можете очистить при размонтировании компонента, вот и все. Четвертый аргумент storeFunc должен быть вашей переменной ref. Включите удаление вашего слушателя в useEffect, и все готово: useEffect(() => { return () => { window.removeEventListener('scroll', storeFunc, false); } }, [storeFunc])
var EV = {
ev: '',
fn: '',
elem: '',
add: function () {
this.elem.addEventListener(this.ev, this.fn, false);
}
};
function cons() {
console.info('some what');
}
EV.ev = 'click';
EV.fn = cons;
EV.elem = document.getElementById('body');
EV.add();
//If you want to add one more listener for load event then simply add this two lines of code:
EV.ev = 'load';
EV.add();
Один из способов сделать это с помощью внешняя функция:
elem.addEventListener('click', (function(numCopy) {
return function() {
alert(numCopy)
};
})(num));
Этот метод заключения анонимной функции в круглые скобки и немедленного ее вызова называется IIFE (Immediately-Invoked Function Expression).
Вы можете проверить пример с двумя параметрами в http://codepen.io/froucher/pen/BoWwgz.
catimg.addEventListener('click', (function(c, i){
return function() {
c.meows++;
i.textContent = c.name + '\'s meows are: ' + c.meows;
}
})(cat, catmeows));
Для меня хорошо сработал следующий подход. Изменено из здесь.
function callback(theVar) {
return function() {
theVar();
}
}
function some_other_function() {
document.body.innerHTML += "made it.";
}
var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));<!DOCTYPE html>
<html>
<body>
<button type = "button" id = "button">Click Me!</button>
</body>
</html>Я застрял в этом, поскольку использовал его в цикле для поиска элементов и добавления к нему списка. Если вы используете его в цикле, то это будет отлично работать.
for (var i = 0; i < states_array.length; i++) {
var link = document.getElementById('apply_'+states_array[i].state_id);
link.my_id = i;
link.addEventListener('click', function(e) {
alert(e.target.my_id);
some_function(states_array[e.target.my_id].css_url);
});
}
Вы можете передать somevar по значению (не по ссылке) с помощью функции javascript, известной как закрытие:
var someVar='origin';
func = function(v){
console.info(v);
}
document.addEventListener('click',function(someVar){
return function(){func(someVar)}
}(someVar));
someVar='changed'
Или вы можете написать обычную функцию переноса, например wrapEventCallback:
function wrapEventCallback(callback){
var args = Array.prototype.slice.call(arguments, 1);
return function(e){
callback.apply(this, args)
}
}
var someVar='origin';
func = function(v){
console.info(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'
Здесь wrapEventCallback(func,var1,var2) выглядит так:
func.bind(null, var1,var2)
Большое спасибо за этот ответ! OP не искал этого, но я думаю, что люди, которые набирают «Как передать аргументы в addEventListener» в Google, будут искать ваш ответ. Просто нужно немного больше пояснений :) Я редактирую.
Довольно старый вопрос, но сегодня у меня была такая же проблема. Самым чистым решением, которое я нашел, является использование концепции карри.
Код для этого:
someObj.addEventListener('click', some_function(someVar));
var some_function = function(someVar) {
return function curried_func(e) {
// do something here
}
}
Называя каррированную функцию, вы можете вызвать Object.removeEventListener, чтобы отменить регистрацию eventListener в более позднее время выполнения.
Рад встретить этот ответ, в котором упоминается каррированная функция. Как бы вы удалили прослушиватель событий?
Приятно видеть хорошую терминологию. Вы должны иметь возможность удалить прослушиватель событий, назвав каррированную функцию. я предложу отредактировать.
Этот ответ будет регистрировать функцию столько раз, сколько вызывается addEventListener, поскольку some_function (var) каждый раз возвращает вновь созданную функцию.
Мне не нравится идея называть каррированную функцию, чтобы удалить слушателя, потому что тогда ur имеет дело с двумя пространствами имен diff, которые вы должны отслеживать
как использовать стрелочную функцию для каррированного fn?
У меня это не работает, так как curried_func недоступен вне some_function. Что терпит неудачу, так это: someObj.removeEventListener('click', curried_func);. Может, я как-то неверно истолковал ваш ответ.
Тебе нужно:
newElem.addEventListener('click', {
handleEvent: function (event) {
clickImg(parameter);
}
});
Это решение может хорошо выглядеть
var some_other_function = someVar => function() {
}
someObj.addEventListener('click', some_other_function(someVar));
или привязать ценности тоже будет хорошо
Если я не ошибаюсь, вызов функции с помощью bind фактически создает новую функцию, возвращаемую методом bind. Это вызовет проблемы позже, или если вы захотите удалить прослушиватель событий, поскольку он в основном похож на анонимную функцию:
// Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);
// Not Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', function() { myCallback });
someObject.removeEventListener('event', /* can't remove anonymous function */);
Так что имейте это в виду.
Если вы используете ES6, вы можете сделать то же самое, но немного чище:
someObject.addEventListener('event', () => myCallback(params));
$form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
function save(data, keyword, name, comment, event) {
Вот как я правильно прошел мероприятие.
Отлично, вот как я почти закончил - просто неправильно передал дополнительное событие в bind, когда его нет (например, в angular), которое автоматически приходит в этом случае.
Да, это работает. Спасибо. Что такое ноль в первом аргументе? А как еще передать этот объект на привязку?
хорошая однострочная альтернатива
element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) {
//some action...
}
Возможно, не оптимально, но достаточно просто для тех, кто не разбирается в супер js. Поместите функцию, вызывающую addEventListener, в отдельную функцию. Таким образом, любые передаваемые в него значения функции сохраняют свою собственную область видимости, и вы можете перебирать эту функцию сколько угодно.
Пример Я работал с чтением файлов, поскольку мне нужно было захватить и отрендерить предварительный просмотр изображения и имени файла. Мне потребовалось некоторое время, чтобы избежать асинхронных проблем при использовании нескольких типов загрузки файлов. Я случайно увидел одно и то же «имя» на всех рендерах, несмотря на то, что загружал разные файлы.
Первоначально вся функция readFile () находилась внутри функции readFiles (). Это вызвало проблемы с асинхронной областью видимости.
function readFiles(input) {
if (input.files) {
for(i=0;i<input.files.length;i++) {
var filename = input.files[i].name;
if ( /\.(jpe?g|jpg|png|gif|svg|bmp)$/i.test(filename) ) {
readFile(input.files[i],filename);
}
}
}
} //end readFiles
function readFile(file,filename) {
var reader = new FileReader();
reader.addEventListener("load", function() { alert(filename);}, false);
reader.readAsDataURL(file);
} //end readFile
просто хотел бы добавить. если кто-то добавляет функцию, которая обновляет флажки в прослушивателе событий, вам придется использовать event.target вместо this для обновления флажков.
В 2019 году много изменений api, лучший ответ больше не работает, без исправления ошибки.
поделитесь рабочим кодом.
Вдохновленный всем вышеперечисленным ответом.
button_element = document.getElementById('your-button')
button_element.setAttribute('your-parameter-name',your-parameter-value);
button_element.addEventListener('click', your_function);
function your_function(event)
{
//when click print the parameter value
console.info(event.currentTarget.attributes.your-parameter-name.value;)
}
У меня очень упрощенный подход. Это может сработать для других, поскольку помогло мне. Это... Когда у вас есть несколько элементов / переменных, которым назначена одна и та же функция, и вы хотите передать ссылку, самым простым решением является ...
function Name()
{
this.methodName = "Value"
}
Вот и все. У меня это сработало. Так просто.
Поскольку ваш прослушиватель событий - click, вы можете:
someObj.setAttribute("onclick", "function(parameter)");
Очень четкая статья по этому поводу: toddmotto.com/avoiding-anonymous-javascript-functions