Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как сделать, чтобы событие вызывалось один раз?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Проблема вот тут:
    const remove = this.on(events

    Метод on у Вас ничего не возвращает, соответственно в remove будет undefined, функции там взяться неоткуда.
    Переменной events нет в скоупе данного метода, очевидно имелась в виду eventName

    А вообще, вместо массива колбэков для события лучше использовать Set, так метод off будет работать за O(1), а не за O(n) как сейчас.

    В методе once можно подписываться на событие через метод on, и отписываться через метод off при его наступлении (так например делает EventEmitter из node.js). Но стоит учесть момент, что off должен работать и для once событий, а у Вас будет записан колбэк созданный в once, а не тот, что передал пользователь. Вообще проще хранить 2 коллекции: для многоразовых для одноразовых событий, ну или параметризовать колбэки (тогда лучше хранить их в Map, где ключи - колбэки, а значения - их параметры).

    Ну и еще обратите внимание, что у Вас в методах emit и once колбэк пользователя вызывается по разному:
    callback.apply(this, args) и callback.call(null, args)
    Ответ написан
    1 комментарий
  • Какой нужен фреймворк для js, под мою задачу?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ответ написан
    Комментировать
  • Какая есть идиома для проверки [null]?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Мне нужно из: [null] получить просто []

    Если таких null много в вперемешку с полезными значениями, то можно отфильтровать:arr = arr.filter(el => el !== null);
    Ответ написан
    Комментировать
  • Что лучше использовать чтобы сделать задержку для отправки комментария?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    На клиенте просто делаем для кнопки:
    button.disable = true;
    setTimeout(() => {
      button.disable = false;
    }, 60_000);

    Основную же проверку нужно делать на сервере, просто не принимая запрос на добавление комментария пока не прошло время после предыдущего, т.к. клиентские проверки обходятся на раз.
    Ответ написан
    1 комментарий
  • Почему не происходит перезаписи значений параметров ф-ции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Потому, что undefined в js - это специальное значение, суть которого быть значением по умолчанию для неинициализированных переменных.
    То есть инициализация переменной значением undefined - это все равно, что инициализация значением по умолчанию.
    Когда Вы в сигнатуре функции пишете b = 10 - это означает, что инициализируй b значением 10 если там инициализация по умолчанию (undefined).
    Ответ написан
    Комментировать
  • Все циклы, кроме for..in, могут работать только с итерируемыми объектами?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    С итерируемыми объектами работают только циклы for-of и for-await-of.

    В современном JS есть следующие виды циклов:

    1. while - цикл с условием
    // где condition - это некоторое выражение, которое можно скастовать к boolean
    while (condition) {
    }
    Данный цикл выполняется, пока условие condition истинно.

    2. do-while - цикл с постусловием
    do {
    } while (condition);
    Данный цикл выполняется как минимум 1 раз, условие condition проверяется после тела цикла и если оно истинно - запускается следующая итерация.

    3. for - цикл с инициализацией, условием и финальным выражением
    for (init; condition; final_expression) {
    }
    
    // основное применение - это цикл со счетчиком, но в целом мы не ограничены в применении
    for (let i = 0; i < 10; ++i) {
    }
    Перед циклом выполняется init, который может быть выражением или оператором объявления переменных (var, let, const). Перед каждой итерацией проверяется условие condition, пока это условие истинно - цикл будет выполняться. После каждой итерации выполняется final_expression.

    4. for-in - цикл по ключам объекта
    // где object - это некоторое выражение, которое можно скастовать к типу object
    for (const key in object) {
    }
    Данный цикл перебирает все перечислимые ключи самого объекта и всех объектов из его цепочки прототипов. Может работать медленно, а ключи из прототипа обычно не требуются, поэтому данный цикл не рекомендуется использовать.

    5. for-of - цикл по итерируемым объектам
    // где iterable - это некоторый объект с методом Symbol.iterator
    for (const value_variable of iterable) {
    }
    Перед итерацией создает итератор вызывая iterable[Symbol.iterator](), перед каждой итерацией дергает метод next у итератора, работает пока в возвращаемом из метода next объекте поле done не станет true, подставляет поле value в переменную value_variable. Цикл в примере выше можно реализовать в виде обычного for:
    {
      const iter = [1, 2, 3][Symbol.iterator]();
      for (let {done, value} = iter.next(); !done; ({done, value} = iter.next())) {
        const value_variable = value;
        {
          // тело исходного цикла
        }
      }
    }


    6. for-await-of - цикл по асинхронно итерируемым объектам
    // где iterable - это некоторый объект с методом Symbol.asyncIterator или методом Symbol.iterator
    for await (const value_variable of iterable) {
    }
    Перед итерацией создает итератор, одним из следующих способов:
    Если в объекте iterable есть метод Symbol.asyncIterator - то вызывает его.
    В противном случае вызывает метод Symbol.iterator.
    В остальном работает как for-of, с той разницей, что дополнительно применяет оператор await к значению итератора и в value_variable попадает то, что вернул данный await.
    Ответ написан
    Комментировать
  • Как преобразовать массив в строку js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    То что у Вас в примере - это вообще не валидный JS.
    Можно с объектами:
    const fields = {
         'Алтайский край': {
              'Барнаул': {}
              'Рубцовск': {}
         },
         'Новосибирская область': {
               'Новосибирск': {}
         },
    };
    console.log(JSON.stringify(fields));
    Ответ написан
  • Как вывести элементы из массива в список?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У Вас только 1 ul на странице, а переменная i у Вас вообще никак не относится к найденным ul
    let ula = document.getElementsByTagName("ul")[0];
    
    for(let i = 0; i < arr.length; i++) {
      ula.insertAdjacentHTML('beforeend', `
      <li>
        <a href="#">${arr[i]}</a>
      </li> 
      `);
    }
    Ответ написан
    1 комментарий
  • Как можно сократить этот код?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const arr = [10, 20, 30, 50, 235, 3000];
    const digits = [1, 2, 5];
    for (const num of arr) {
      const digit = (num / 10 ** (Math.log10(num) | 0)) | 0;
      if (digits.includes(digit)) {
        console.log(num);
      }
    }
    Ответ написан
    Комментировать
  • Сервер возвращает ответ на фронт в виде значений, как изменить стили в зависимости от этих значений?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вообще выглядит так, что у Вас все же ограниченный набор состояний, которые можно заранее описать классами в стилях и переключать эти классы по ответу от сервера.

    Но если все же стили в каждом конкретном случае определяются сервером, то можно генерировать их на лету. Правда есть проблема, с тем, что такие стили не редактируются через devtools (хотя сейчас может уже что изменилось). Несколько лет назад я сталкивался с подобной задачей, когда стили для некоторых вариантов отображения UI задавались пользователями, я тогда написал вот такой модуль для решения этой задачи:
    https://gist.github.com/bingo347/cb8e62606e206c009...
    Ответ написан
    1 комментарий
  • Почему в массив добавляються лишние елементы?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    А Вы на листочке по шагам пройдите свой алгоритм...

    Я вас больше удивлю:
    einzigartig([1, 2, 3, 4, 5]) // [1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5]


    Подумайте хорошо, когда срабатывает это условие: if(arr[i] !== arr1[j]) ведь и i и j пробегают все элементы массива

    А еще Ваша функция некорректно отработает, если на вход придет пустой массив

    P.S. именовать сущности на языках отличных от английского не очень хорошая идея... Я например только с гуглом смог понять, что это немецкий и как оно переводится...
    Ответ написан
    Комментировать
  • Можно объединить electron.js приложение с низкоуровневым кодом?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У электрон под капотом node.js, а значит под него можно писать нативные аддоны так же как к node.

    В плане Rust для этого есть 2 фреймворка:
    https://neon-bindings.com/
    https://napi.rs/

    Из личного опыта, неон я пробовал, показывает он себя очень хорошо, но под капотом он не полностью использует napi, а так же задействует низкоуровневое api ноды для C++, что требует пересборки проекта под разные версии ноды, с электроном тут проще, так как мы тащим конкретную версию ноды с собой. Но с электроном есть другая особенность в плане нативных аддонов - кроссплатформенность. По сути нативные аддоны ноды - это просто динамически подгружаемая библиотека (.dll на винде, .so на линуксе и .dylib на маке), соответственно нужно будет делать билд под все платформы, под которые мы делаем наше приложение.
    До napi.rs у меня руки пока не дошли, но выглядит очень хорошо. И на сколько я понял оно полностью сделано поверх napi - высокоуровневым C-abi совместимым апи, не требующем пересборки под разные версии ноды.

    Насчет OpenGL/Vulkan/Metal - помимо node.js у электрон под капотом хромиум, в котором есть WebGL, который в свою очередь JS биндинг к OpenGL. Это по сути и есть OpenGL в чистом виде, просто прокинутый в JS. Но апи OpenGL весьма низкоуровневое, в отличии от DirectX/Vulkan/Metal
    Ответ написан
    1 комментарий
  • Js проверка isset?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Оператор ! - это булево отрицание. И он приводит свой аргумент к типу boolean. Автор не открыл Америку, и это используется. Но использовать нужно с умом.
    Значения приводимые к false - это undefined, null, '' (пустая строка), 0, 0n (bigint 0), NaN.
    Соответственно, когда у нас есть например строка или undefined или например число или undefined - такая проверка на undefined может быть небезопасна, так как она отсечет еще и пустую строку, 0 и NaN.

    !! - это всего лишь 2 идущих подряд оператора !, это такое популярное сокращение для быстрого каста к boolean.
    Еще автор статьи предлагает использовать !!!, но это бессмысленно, так как тройное отрицание даст тоже самое что и одинарное.
    Ответ написан
    1 комментарий
  • Как из строковых литералов сделать тип массива?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В TS есть 2 варианта итерироваться по частям юнион типа - это условные типы и итерация по ключам, притом итерация по ключам ограничена типом number | string | symbol

    Условные типы проверяют условие для каждого варианта юниона, а значит позволяют трансформировать каждый из вариантов по отдельности:
    type MyFunc = <N extends string>() => (N extends string ? Field<N> : never)[];
    но возвращаемый тип так же будет юнионом:({ name: "town" } | { name: "city" })[]

    Сделать кортежный тип из юниона не выйдет, так как в юнионе не определен порядок, тип "town" | "city" это тоже самое, что и тип "city" | "town".
    Но можно сделать кортеж из кортежа:
    type MyFunc = <N extends string[]>() => {
        [K in keyof N]: N[K] extends string ? Field<N[K]> : never;
    };
    
    myFunc<["town", "city"]>()


    Ну и в реальном коде гораздо удобнее, когда дженерик выводится из аргументов, а для того что бы TS сам вывел кортежный тип из абстрактного массива, данный массив нужно помечать as const, что так же делает его readonly массивом. Но принимать аргументы через readonly там где нам не нужно их мутирорвать - это вообще хорошая практика. Полный пример будет выглядеть так:
    https://www.typescriptlang.org/play?#code/C4TwDgpg...
    Ответ написан
    Комментировать
  • Как исправить ошибку: Failed to set the 'currentTime' property on 'HTMLMediaElement': The provided double value is non-finite?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Свойство duration не доступно пока не загружены метаданные видео
    Вам нужно ждать события:
    https://developer.mozilla.org/en-US/docs/Web/API/H...
    Ответ написан
    Комментировать
  • Почему функция не работает?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ну во-первых, чего Вы хотели добиться вот этим кодом?
    for (const letter of target) {
      if ( letter.toLowerCase() !== letter.toUpperCase() ) {
        direct = letter + direct;
        reversed = letter + reversed;
      }
    }


    Во-вторых, данная задача легко решается за O(n/2), а у Вас как минимум тут O(n):target.split('').reverse().join('')

    Нормальный алгоритм для этой задачи такой:
    1. Заводим 2 переменные под индексы символов, одна будет смотреть на начало строки (изначальный индекс 0), другая на конец строки (изначальный индекс target.length - 1).
    2. Идем циклом по строке с обоих сторон, увеличивая первый индекс и уменьшая второй на каждой итерации.
    2.1. Если символ под индексом не подходящий (пробел, знак препинания и т.д.), то его надо пропустить, сместив соответствующий индекс еще на 1 вне очереди. Подсказка: если нужна только латиница, то ее коды символов лежат в диапазонах 65-90 и 97-122 (у строки есть метод charCodeAt), для кириллицы диапазоны 1072-1103, 1040-1071, 1105, 1025.
    2.2. Если текущие символы строки, с учетом приведения их к единому регистру не равны, то можно дальше не проверять и сразу возвращать false.
    2.3. Если индексы стали равны или пересекли друг друга (индекс с конца меньше индекса с начала), то можно однозначно возвращать true.
    Ответ написан
    Комментировать