Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   addEventListener для Всех событий (https://javascript.ru/forum/events/84324-addeventlistener-dlya-vsekh-sobytijj.html)

Andy_kun 05.08.2022 23:09

addEventListener для Всех событий
 
Подскажите пожалуйста, можно ли привязать/вызвать addEventListener - так, чтобы callback срабатывал на Все события, которые генерируется для данного элемента при взаимодействии с ним ?

То есть я понимаю, что сигнатура функции addEventListener() - содержит, как я понимаю два обязательных параметра, но может, как то можно все таки ?

ksa 06.08.2022 10:59

Цитата:

Сообщение от Andy_kun
То есть я понимаю, что сигнатура функции addEventListener() - содержит, как я понимаю два обязательных параметра, но может, как то можно все таки ?

Т.е. понимание не может преодолеть желание? :D

Andy_kun 06.08.2022 11:30

Цитата:

Сообщение от ksa (Сообщение 547197)
Т.е. понимание не может преодолеть желание? :D

Да:)

Нашел такое решение:

Object.keys(window).forEach(key => {
    if (/^on/.test(key)) {
        element.addEventListener(key.slice(2), event => {
            console.log(event);
        });
    }
});

Aetae 06.08.2022 12:14

Andy_kun, тогда уж так:
function addAllEventListeners(element, callback) {
  for (const key in element) if(key.startsWith('on')) {
    element.addEventListener(key.slice(2), callback);
  }
}
потому что разные элементы могут поддерживать разные события.)

Ну и всякие особые события (типа DOMContentLoaded) и кастомные собтия так не навесить всё равно.

Andy_kun 06.08.2022 13:13

Цитата:

Сообщение от Aetae (Сообщение 547201)
Andy_kun, тогда уж так:
function addAllEventListeners(element, callback) {
  for (const key in element) if(key.startsWith('on')) {
    element.addEventListener(key.slice(2), callback);
  }
}
потому что разные элементы могут поддерживать разные события.)

Ну и всякие особые события (типа DOMContentLoaded) и кастомные собтия так не навесить всё равно.

Спасибо!

А подскажите пожалуйста, а чем:

Object.keys(element).forEach(key...)


Отличается от:

for (const key in element)
{
...
}

Aetae 06.08.2022 13:18

Andy_kun, Object.keys берёт ключи только у самого объекта, for in производит итерацию по всем enumerable ключам, включая унаследованые. В большинстве случаев Object.keys предпочтительней и надёжней, но в данном случае html элементы имеют глубокую иерархию наследования, потому for in приходится как нельзя кстати.

Andy_kun 06.08.2022 13:22

Цитата:

Сообщение от Aetae (Сообщение 547203)
Andy_kun, Object.keys берёт ключи только у самого объекта, for in производит итерацию по всем enumerable ключам, включая унаследованые. В большинстве случаев Object.keys предпочтительней и надёжней, но в данном случае html элементы имеют глубокую иерархию наследования, потому for in приходится как нельзя кстати.


То есть в данном случае for..in - это аналог: Object.getOwnPropertyNames() ?

Aetae 06.08.2022 13:32

Andy_kun, нет, for in, если условно, равносильно рекурсивному вызову Object.keys вверх по цепочке наследования (Obect.keys(el) + Object.keys(Object.getProtiotypeOf(el)) + ...). Object.getOwnPropertyNames получает также как и keys только свойства самого объекта, но в отличение от keys он получает все свойства, а не только перечислимые(enumerable).

{
const parent = {
  parentProp: 'bar'
};
const child = Object.create(parent, {
  nonEnumerableChildProp: {
    enumerable: false,
    value: 'buz'
  }
});
child.childProp = 'foo';

function *keys (obj) {
  for (const key in obj)
    yield key;
} 
  
console.log('child.parentProp', child.parentProp);
console.log('child.childProp', child.childProp);
console.log('child.nonEnumerableChildProp', child.nonEnumerableChildProp);

console.log('object.keys', Object.keys(child));
console.log('object.getOwnPropertyNames', Object.getOwnPropertyNames(child));
console.log('for in', [...keys(child)]);
}

Andy_kun 06.08.2022 13:52

Цитата:

Сообщение от Aetae (Сообщение 547205)
Andy_kun, нет, for in, если условно, равносильно рекурсивному вызову Object.keys вверх по цепочке наследования (Obect.keys(el) + Object.keys(Object.getProtiotypeOf(el)) + ...). Object.getOwnPropertyNames получает также как и keys только свойства самого объекта, но в отличение от keys он получает все свойства, а не только перечислимые(enumerable).

{
const parent = {
  parentProp: 'bar'
};
const child = Object.create(parent, {
  nonEnumerableChildProp: {
    enumerable: false,
    value: 'buz'
  }
});
child.childProp = 'foo';

function *keys (obj) {
  for (const key in obj)
    yield key;
} 
  
console.log('child.parentProp', child.parentProp);
console.log('child.childProp', child.childProp);
console.log('child.nonEnumerableChildProp', child.nonEnumerableChildProp);

console.log('object.keys', Object.keys(child));
console.log('object.getOwnPropertyNames', Object.getOwnPropertyNames(child));
console.log('for in', [...keys(child)]);
}


Еще раз спасибо! А где можно про этот обход почитать и про "ключевое слово" в данном случае key ?
А что если для этих свойств нужно получить значения ?
Существует аналог слова "key" для values ?

PS:for...in - только для свойств. Тут написано: https://developer.mozilla.org/ru/doc...ments/for...in

Как же тогда сопоставить этим свойствам их значения?

Aetae 06.08.2022 14:19

Andy_kun, for in - это просто цикл, key, соответственно, просто переменная.)
Значения получаем также как и во всех "дедовских" циклах, руками:
{
const obj = {
  foo: 1,
  bar: 2
}

for (const key in obj) {
  const value = obj[key];

  console.log(key, value)
}
}


Ну и в целом рекомендуется не злоупотреблять for in там где работает Object.keys. В большинстве случаев вы не хотите лезть в цепочку наследования с шансом притащить что-то ненужное.)


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