Ответы пользователя по тегу JavaScript
  • Как сгруппировать id объектов, у которых совпадают остальные свойства?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Нет смысла выделять первый id как особый, и добавлять к нему в массив match другие похожие — все id с одинаковыми прочими значениями равноправны. Поэтому предлагаю как результат просто массивы, где собраны id с совпадающими свойствами.

    Понадобится хэш из ключей, исключая id, упорядоченных по алфавиту, и значений. Этот отпечаток будет одинаков у совпадающих объектов, несмотря на разные id (и разный порядок ключей).

    Получаем объекты { id, hash }, затем составляем «словарь», где ключи – хэши, а значения – Set'ы с id, у которых оказался одинаковый хэш. Set'ы – чтобы не повторялись одинаковые id.

    Потом остаётся из этих Set'ов сделать обычные массивы.
    const arr = [
      { id: 1, we: 'cn', le: null },
      { id: 2, le: null, we: 'cn' },
      { id: 3, we: 'cn', le: 'car' },
      { id: 1, we: 'cn', le: null },
    ];
    
    const dict = arr
      .map(({ id, ...obj }) => {
        const keys = Object.keys(obj).sort();
        const ordered = keys.reduce((acc, c) => {
          acc[c] = obj[c];
          return acc;
        }, {});
        return { id, hash: JSON.stringify(ordered) };
      })
      .reduce((acc, c) => {
        (acc[c.hash] ??= new Set()).add(c.id);
        return acc;
      }, {});
    
    Object.values(dict).map(s => [...s]); // [ [1, 2], [3] ]
    Ответ написан
    9 комментариев
  • Как исправить код, чтобы он заработал?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    HTML отдельно, JS отдельно.
    Слушателей событий добавлять через addEventListener()
    Забыть про document.write(). Вместо этого использовать element.innerText = "Хабр"; например.
    Обновлять запись баланса понадобится из двух разных мест: в начале, и при каждом выигрыше. Поэтому – в функцию.

    Ответ написан
  • Как импортировать все export default файлы из папки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    «Кроме импорта каждого» стандартных вариантов нет.

    Можно сделать в папке index.js, в который таки прописать каждый файл в папке.
    // papka/index.js
    import a from './a';
    import b from './b';
    // ...
    
    export { a, b, };


    Зато потом удобно
    // main.js
    import * as Papka from '/papka';
    
    const { a, b } = Papka;
    console.log(a, b);
    
    // или
    Object.entries(Papka).forEach(([key, value]) => console.log(key, value));
    Ответ написан
    1 комментарий
  • Как выполнить последовательно функцию js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    async/await тут лишний, достаточно просто
    const get_element_list = id => {
      return axios({
        url: `${url_hook}/lists.element.get.json`,
        method: 'post',
        data: {
          IBLOCK_TYPE_ID: 'lists',
          IBLOCK_ID: 17,
          filter: {
            PROPERTY_70: 1,
            PROPERTY_74: id,
          },
        },
      }).then(response => {
        const result = response.data.result[0];
        console.log(result, response.status, response.data); // посмотрите, что тут
      });
    };
    Ответ написан
    Комментировать
  • Как записать надпись на кнопке в cookies?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Сохранять удобнее не в куках, а в localStorage.

    Нужна модель данных. Есть кнопки, у каждой, наверное, уникальный id. На случай, если их перемешают иначе, или добавится новая — полагаться только на порядковый номер в коллекции, i, не годится: сейчас на 3-м месте одна кнопка, завтра окажется другая, а мы для неё запомнили включённое состояние.

    Итак, есть кнопки с уникальными id. Кнопка может быть добавлена или не-добавлена в избранное. Булево значение: true или false. Запоминать будем набор пар ключ-значение. Ключ id, значение true/false. Что-то типа { "abc123": true, "xyz789": false, }

    При загрузке страницы проверить, есть ли сохранённый комплект? Применить его. Остальным кнопкам значение по-умолчанию.

    При любом изменении кнопок — сохранять обновлённую коллекцию.

    Надписи показывать исходя из true/false в этой коллекции.
    Ответ написан
    Комментировать
  • Интересная задача на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Решение не верно, т.к. расчитывает только на эти 4 имени. Что, если там будут другие?

    Алгоритм:
    1. составить объект, где ключи – имена, а значения – счётчики, сколько раз имя встретилось.
    2. после полного подсчёта, найти максимум и минимум счётчиков.
    3. собрать имена, у которых счётчик равен максимуму или минимуму. Каждого, теоретически, может оказаться больше одно, поэтому – в массивы имён.
    4. пройти по всем ключам объекта со счётчиками, и исключить имена, которые есть среди макс и мин. – останутся «остальные».


    spoiler
    const mostLeastAndTheRest = names => {
      const dict = names.reduce((acc, name) => ((acc[name] ??= 0), acc[name]++, acc), {});
      // { "Женя": 3, "Иван": 1, "Виктор": 4, "Константин": 1 }
    
      const values = Object.values(dict);
      const max = Math.max(...values);
      const min = Math.min(...values);
    
      const entries = Object.entries(dict);
      const winners = entries.filter(([_, value]) => value === max).map(([key, _]) => key);
      const losers = entries.filter(([_, value]) => value === min).map(([key, _]) => key);
      const rest = Object.keys(dict).filter(name => !winners.includes(name) && !losers.includes(name));
      return { winners, losers, rest };
    };
    
    mostLeastAndTheRest(['Женя', 'Женя', 'Иван', 'Женя', 'Виктор', 'Виктор', 'Константин', 'Виктор', 'Виктор']);
    /*
    {
      "winners": [ "Виктор" ],
      "losers": [ "Иван", "Константин" ],
      "rest": [ "Женя" ]
    }
    */


    Ещё вопрос — особый случай, если всех одинаковое число, то все – «победители» или «проигравшие» ?
    Ответ написан
    1 комментарий
  • Как отправлять сообщение вебсокета другим подключениям, не текущему?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Сервер, приняв событие А, знает, с какого соединения он его принял.

    Это соединение и исключать при рассылке всем (остальным).

    Не знаю, как у вас реализована рассылка-всем, но, вероятно, есть цикл перебора активных подключений (у каждого свой id), и отправка сообщения. В этом цикле можно проверять, не тот ли это id, с которого пришло входящее.
    Ответ написан
  • Как скрыть API KEY телеграмма?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Всё, что оказалось в браузере — утекло.

    Поэтому ключа не должно быть «просто в js», никак.

    Нормальный вариант отправлять сообщение в ваш бэкенд, а тот уже, используя ключ, переправит сообщение в тележку.

    Копать в направлении POST-запроса из JS с помощью fetch() или, удобнее, axios.
    На бэке принимать сообщение и отправлять его в тележку, используя curl
    Ответ написан
    Комментировать
  • Как сделать русское лото?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    нужен рандом без повторений. Как вариант, сделать массив из всех доступных чисел 1..99, и каждый раз вынимать случайно выбранное число из массива — так точно повторов не будет.

    // массив 1..99
    const range = Array(99)
      .fill()
      .map((_, i) => i + 1); // массив 1..99
    
    // 6 неповторяющихся выигрышных
    const win = Array(6)
      .fill()
      .map(() => range.splice(Math.floor(Math.random() * range.length), 1).pop())
      .sort((a, b) => a - b);
    
    // [ 1, 55, 69, 76, 91, 92 ]
    Для выбора выпавших чисел игрока этот же range уже использовать нельзя – в нём не хватает 6 чисел.
    Ответ написан
    5 комментариев
  • Как при нажатии на элемент узнать его место в массиве у родителя?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    у parent'а возьмите свойство children, в нём найдите indexOf кликнутого элемента.

    Такой же вопрос с ответами: https://qna.habr.com/q/1177140
    Ответ написан
    2 комментария
  • Как корректно вывести значение из data атрибута в инпут?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    -$(this).parents( ".wrapper" ).find(".btn-order-show").attr('data-color', choice);
    +$(this).parents( ".wrapper" ).find(".btn-order-show").data('color', choice);
    Ответ написан
  • Как записать данные в переменную после выполнения axios?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Опять кто-то не понял асинхронности.

    axios.get() возвращает Promise. Его метод .then() выполнится не сразу, а когда-то потом, когда будет получен результат запроса. Представьте, что интернет очччеенньь мееедленнныыыйй.

    Зато остальной код выполняется привычно сразу («синхронно»). В т.ч. и console.log() в последней строке – сразу же за созданием объекта. Но на тот момент веб-запрос ещё не выполнился.

    TL&DR надо ждать. Это можно делать несколькими способами: коллбэком, промисами, обёрткой вокруг них async/await.
    Например
    class Address {
      address = null;
      data = [];
     
      data() {
        return this.data;
      }
      
      constructor(address) {
        this.address = address;
      }    
    
      fetchInformation() {
        return axios.get(`${API_BASE}/getAddressInformation`, {
          params: {
            address: this.address
          }
        }).then(({ data }) => this.data = data);
      }
    }
    
    async function initialize() {
      const address = new Address(TEST_WALLET);
      await address.fetchInformation();
      console.log(address);
    }
    
    initialize();
    Ответ написан
    4 комментария
  • DOM. Конструктор класса?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Некий сумбур вопроса без примеров кода попробую разобрать, отталкиваясь от знаков вопроса.

    У всех (ну, почти) объектов в JavaScript в корне цепочки наследования — глобальный Object. У прототипа которого есть свойство constructor. Это ссылка на функцию, создавшую сей инстанс.

    У функций в JavaScript есть свойство name.

    Не важно, как именно создан объект. Если он — объект, у него, скорее всего, есть конструктор:
    const el = document.createElement('div');
    el.constructor.name // "HTMLDivElement"


    А вот с классом
    class Habr {
      constructor(q) {
        this.q = q;
      }
    }
    
    const h = new Habr('есть конструктор?');
    h.constructor.name  // "Habr"
    Ответ написан
    Комментировать
  • Как это расшифровать?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    можно предположить, что это массив, где разделитель 'x'. Это даст 71 число.
    большинство начинается с "2004", но каждое 9-е — с "2005". Эти 2005-е все одинаковы: 20056745.
    Итого 8 групп по 8, и 7 разделителей между ними. 64 + 7 = 71

    Многие значения после префикса"2004" повторяются:
    7155 7155 7155 7155 7155 7155 7155 7155
    6881 6881 6881 6881 6881 6881 6881 6881
    6881 6881 6881 6881 6881 6881 6881 6881
    7429 7566 7429 7429 7566 7429 7429 7429
    8114 7018 8114 7840 6881 7840 7840 8114
    7703 7703 7840 7018 6881 7018 7155 7703
    7155 7840 7566 7566 7292 7566 8114 7155
    7018 7703 7977 7566 7155 7566 7155 7018
    код для получения
    const value = '20047155x20046881x20046881x20047429x20048114x20047703x20047155x20047018x20056745x20047155x20046881x20046881x20047566x20047018x20047703x20047840x20047703x20056745x20047155x20046881x20046881x20047429x20048114x20047840x20047566x20047977x20056745x20047155x20046881x20046881x20047429x20047840x20047018x20047566x20047566x20056745x20047155x20046881x20046881x20047566x20046881x20046881x20047292x20047155x20056745x20047155x20046881x20046881x20047429x20047840x20047018x20047566x20047566x20056745x20047155x20046881x20046881x20047429x20047840x20047155x20048114x20047155x20056745x20047155x20046881x20046881x20047429x20048114x20047703x20047155x20047018';
    
    value.split('x').map(s => +s.replace(/^2004/, ''))
      .reduce((acc, c, i) => {
      if ((i + 1) % 9 !== 0) {
        (acc[i % 9] ??= []).push(c);
      }
      return acc;
    }, [])
      .map(ar => ar.join(' '))
      .join('\n')

    Причём, уникальных значений там всего 10:
    7155, 6881, 7429, 8114, 7703,
    7018, 7566, 7840, 7977, 7292
    как получить
    [...value.split('x').map(s => +s.replace(/^2004/, ''))
      .reduce((acc, c, i) => {
      if ((i + 1) % 9 !== 0) {
        acc.add(c);
      }
      return acc;
    }, new Set())].join(', ')
    Ответ написан
    3 комментария
  • Как добавить следующий символ к переменной js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Если непременно хочется с циклом и условиями, то так:
    function makeAbbr(words) {
      let result = '';
      for (let i = 0; i < words.length; i++) {
        const char = words[i];
        if (char !== ' ' && (i === 0 || words[i - 1] === ' ')) {
          result += char;
        }
      }
      return result;
    }
    символ — не пробел, И, к тому же, самый первый в тексте, ИЛИ перед ним был пробел.

    Но приятнее, конечно, разбить текст на массив слов, и от каждого взять первую букву:
    const makeAbbr = words =>
      words
        .trim() // убрать пробелы по краям строки
        .split(/\s+/) // разбить по пробелу(ам) в массив
        .map(w => w[0].toUpperCase()) // от каждого взять первые буквы
        .join(''); // склеить в строку
    
    makeAbbr(' мир    труд май') // "МТМ"
    Ответ написан
    4 комментария
  • Как можно улучшить код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    1. обновление innerHTML на каждой итерации — плохо (медленно). Лучше один раз собрать весь HTML в строку, и один раз заменить innerHTML.

    2. неаккуратность — «условно договорились», что в массиве такие-то значения идут на таких-то позициях. Это нигде явно не указано и следующему разработчику придётся догадываться, что там под нулевым индексом, а что под третьим.

    3. данные в примере точно можно генерить из последовательности 0..11. В таком случае можно так:
    spoiler
    const html = new Array(12)
      .fill()
      .map((_, i) => {
        const parallax = `./src/img/parallax/${i & 1 ? 2 : 1}.jpg`;
        const hero = './src/img/home/hero.jpg';
        const title = `Code №${i + 1}`;
        const codepen = `Codepen-${i + 1}`;
    
        return `
          <div class="portfolio__codepen">
            <div class="portfolio__codepen-background"></div>
            <img class="portfolio__codepen-image" src="${parallax}">
            <div class="portfolio__codepen-down">
              <img src="${hero}" class="codepen-down__hero">
              <div class="codepen-down__text">
                <h4>${title}</h4>
                <h5>${codepen}</h5>
              </div>
              <a href="#codepen" class="codepen-down__link">Source</a>
            </div>
          </div>
        `;
      })
      .join('\n');
    
    item.innerHTML = html;
    Ответ написан
  • Каким образом можно создать объект, используя имя класса, записанное в строке?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    как всегда с динамическими именами в JavaScript, нужен объект со свойствами. К свойствам можно обращаться динамически, брать их имя из строки:
    const A = class { constructor() { this.name = 'I am A';} };
    const B = class { constructor() { this.name = 'I am Bee';} };
    const allClasses = { A, B };
    
    const className = 'A';
    
    const instance = new allClasses[className]();
    console.log(instance.name); // I am A
    Ответ написан
    Комментировать
  • Uncaught TypeError: Cannot read properties of undefined (reading 'then')?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    1. thunk (на англ.) задуман как кусок кода, который выполняется «потом» и независимо от UI.
    Так что затея что-то там оборвать «в форме» кажется неправильной. Всё, что делает thunk – берёт что-то из состояния через getState() и рано или поздно меняет состояние через dispatch().

    2. внутри async функции возвратить Promise.reject() — то же, что бросить Exception в обычном синхронном коде. Подробнее.
    Ответ написан
  • Как реализовать переход уровней?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    сделать кнопку «На следующий уровень!»,
    по нажатию всё сбросить и начать со следующим уровнем.
    Ответ написан
    Комментировать
  • Как открыть ссылку в текущем окне?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    window.location = 'https://habr.com/';
    
    window.location.href = 'https://habr.com/';
    
    window.location.assign('https://habr.com/');
    Ответ написан
    Комментировать