Ответы пользователя по тегу JavaScript
  • Сервер возвращает ответ на фронт в виде значений, как изменить стили в зависимости от этих значений?

    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.
    Ответ написан
    Комментировать
  • Как округлить целое число?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Отбросить лишние разряды с нужной точностью:
    function truncInteger(number, precision) {
      return number - (number % precision);
    }
    console.log(truncInteger(1000040, 100));
    console.log(truncInteger(1200040, 100));

    Математическое округление:
    function roundInteger(number, precision) {
      return Math.round(number / precision) * precision;
    }
    console.log(roundInteger(1000040, 100));
    console.log(roundInteger(1200040, 100));
    console.log(roundInteger(1000080, 100));
    console.log(roundInteger(1200080, 100));
    Ответ написан
    Комментировать
  • Как реализуется enum в JS из Typescript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Можете, пожалуйста, объяснить, что выполняет эта часть кода: (Membership || (Membership = {})
    Если в Membership не falsy значение (например объект), то передать ссылку на него в функцию, иначе (если в Membership undefined) присвоить в Membership новый объект и передать ссылку на него в функцию

    И почему это всё обёрнуто в функцию?
    Сложно сказать, думаю кто-то скопировал код отсюда в код сюда и не стал париться, так как в обоих случаях есть declaration merging, о котором уже написал Aetae

    А вообще стоит узнать про const enum, который не оставляет артефактов в JS и в подавляющем большинстве случаев его достаточно.
    Ответ написан
    Комментировать
  • В чем разница между pdf.js и pdfjs-dist?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    но зачем скомпилированную версию называть отдельным именем и выделять под нее отдельный репозиторий
    dist репозиторий может автоматически разворачиваться на CDN через CI или push-хук, при этом в нем нет исходников и на него может быть ограниченный доступ на запись, а в репо с исходниками нет артефактов сборки. Кроме того можно быстро откатить кривой релиз через revert.
    Ну и у github нормальный CI появился относительно недавно, и старые проекты вполне могут использовать такую схему.

    Что-то я не пойму в чем разница между pdf.js и pdfjs-dist?
    В одном лежат исходники, в другом собранные бандлы.

    Правильный вариант - это или подключать собранный бандл с CDN или ставить с npm и собирать самому.
    Ответ написан
  • Как зациклить setTimeOut?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const preloadImages = document.querySelectorAll('.pr-bub');
    const preloadImagesAnimationInterval = setInterval((state) => {
        const item = preloadImages[state.index];
        item.classList.toggle('animationPreBub', state.addClass);
        state.index--;
        if (state.index < 0) {
            state.addClass = !state.addClass;
            state.index = preloadImages.length - 1;
        }
    }, 300, {
        addClass: true,
        index: preloadImages.length - 1,
    });
    Ответ написан
    3 комментария
  • Являются ли промисы асинхронными?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    new Promise(resolve => {
      // здесь код выполняется синхронно
      resolve();
    }).then(() => {
      // здесь уже асинхронно, в ближайшем микротаске после вызова resolve выше
    });
    
    Promise.resolve().then(() => {
      // здесь тоже асинхронно, в ближайшем микротаске
    });


    много вычислений
    Это не про асинхронность.
    Асинхронность - это про кооперативную многозадачность, то есть промис может только отложить вычисления на потом, но они все равно заблокируют поток, который у JS всего один.
    А для "много вычислений" без блокирования основного потока, эти "много вычислений" нужно выносить в отдельный поток. В JS для этого есть воркеры. А вот уже результат от воркера можно ждать асинхронно.
    Ответ написан
    Комментировать
  • Почему не работает child_process electron?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Скорее всего проблема с путями для 'easyvk.js'.
    Во-первых, лучше всегда вычислять абсолютный путь до файла.
    Во-вторых, electron-packager пакует приложение в asar, и если require пропатчен для работы с ним, то child_process скорее всего нет и нужен анпакинг файла перед запуском.
    Ответ написан
  • Вопросы по REST API?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Во-первых, REST - это не стандарт, не строгие правила, это рекомендации.
    Вся суть этих рекомендаций сводится к двум вещам:
    - Каждый ресурс (документ, данные о сущности) имеет свой собственный URI
    - Для каждого действия с ресурсом предлагается в соответствие свой HTTP метод запроса

    Теперь по вопросам:
    1. Если данные json и html - это просто разные представления одного ресурса, то они вполне могут жить на одном URI. Например разное представление отдается в зависимости от HTTP заголовка Accept.
    2. REST никак не регламентирует, как Вам строить приложение. Это может быть отдельный запрос к сущности "роль" или быть частью сущности "пользователь", решать Вам.
    3. Опять же, REST тут вообще не причем. В REST нет никаких БД, сессий или еще чего либо, что Вы там под капотом используете инкапсулировано от клиента.
    4. CSRF делается как и в любом другом случае. Вот статья есть: https://habr.com/ru/post/318748/
    Ответ написан
    4 комментария
  • Почему не происходит перерисовка в самописном react-redux?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    state.firstname = action.payload.firstname;тут Вы мутируете предыдущий стейт, что потенциально может привести к невозможности сравнить стейты.

    reducer(state, action);возвращаемый стейт никуда не записывается

    callback();А вот тут может быть потенциально ошибка, так как callback может быть undefined
    Ответ написан
    1 комментарий
  • Как изменить значение обьекта на имя?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Object.keys(object[key]) = newobject[key];
    Вот на этой строчке у Вас ошибка, в JS нельзя присвоить что-то любому выражению, только переменной или полю объекта.
    Ответ написан
    Комментировать