Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как в данном коде победить ошибку ESLint Assignment to property of function parameter 'acc'. (no-param-reassign)?

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

    Но все же есть 2 способа обойтись без комментария:

    1. Просто затыкаем линтер, но по сути делаем то же самое, то есть мутируем аргумент acc, но по хитрому:
    var items = Object.values(msg).reduce((acc, curr) => {
      curr.category.forEach(item => Object.assign(acc, {[item.id]: item.cat_name}));
      return acc;
    }, {});


    2. пишем действительно иммутабельно, ловим небольшой оверхед по производительности, зато получаем более надежное решение:
    const items = Object.values(msg).reduce(
      (acc, curr) => Object.assign({}, acc, curr.category.reduce(
        (acc, item) => Object.assign({}, acc, {[item.id]: item.cat_name}),
      {})),
    {});
    Ответ написан
  • Как сделать, чтобы данные из одной функции передавались только после того, как завершится асинхронный запрос в другой функции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    let lock;
    function a(data) {
        Promise.resolve(lock).then(() => send(data));
    }
    
    function b() {
        lock = Promise.all([
            lock,
            asyncRequestPromise().catch(err => {
                // обработка ошибки, иначе все упадет
            })
        ]).then(() => lock = void 0); // чистим память
    }
    
    a("some data");
    Ответ написан
    Комментировать
  • Функция .html('') не видит полностью код?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Во-первых, если js внутри html, то строки содержащие </script> нужно разбивать:
    $('.map').html('<script charset="utf-8" async src="https://api-maps.yandex.ru/services/constructor/1.0/js/?um=constructor%3A45374b4f36193c2c3bb5a22a9bffed35b78e3e041596ce43450258bbf7529fad&amp;width=100%25&amp;height=598&amp;lang=ru_UA&amp;scroll=false"> </sc' + 'ript>')


    Во-вторых, не уверен, что jQuery настолько умный, чтоб автоматом нормализовать вставку скрипта, по этому меняем эту строку так:
    var script = document.createElement('script');
    script.async = true;
    script.src = 'https://api-maps.yandex.ru/services/constructor/1.0/js/?um=constructor%3A45374b4f36193c2c3bb5a22a9bffed35b78e3e041596ce43450258bbf7529fad&amp;width=100%25&amp;height=598&amp;lang=ru_UA&amp;scroll=false';
    $('.map').append(script);
    Ответ написан
    1 комментарий
  • Что не так с кодом js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Что не так с кодом js?
    он некорректный с самой первой строки...

    // тут очевидно было пропущено объявление переменной куда сохраняем полученный из DOM canvas
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    // вангую, что тут не объявленные переменные, и их нужно объявить
    var x = 0;
    var y = 0;
    var x1 = 0;
    var y1 = 0;
    var g = 4;
    var b = 7;
    
    // тут норм, но все же стоит включить себе линтер
    // ибо порядок в коде == порядок в голове
    var ground1 = new Image();
    ground1.src = "Ground.png";
    var pick1 = new Image();
    pick1.src = "Pick.png";
    
    // а вот в функции draw началась полная дичь...
    function draw() {
      ctx.clearRect(0,0,316,632); // очистку перенес внутрь функции отрисовки
    
      // тут я вырезал addEventListener - ибо добавлять нового подписчика на каждой отрисовке - дичь полнейшая
      // пристрелите того, кто Вас этому научил, так Вы сделаете этот мир лучше
    
      if(g < b) {
        ctx.drawImage(ground1, x, y);
        x+=32;
        if(x-32 > 290){
          x = 0;
          y+=32;
        }
        if(y-32 > 578){
          y = 0;
          x = 0;
        }
      }
    
      // я так думаю эту картинку надо рисовать после фона
      ctx.drawImage(pick1, x1, y1);
    
      requestAnimationFrame(draw); //зациклим анимацию
    }
    
    // анимировать что-то по таймеру плохая затея, есть более подходящие инструменты
    requestAnimationFrame(draw);
    
    // подписку на событие клавиатуры вынес из отрисовки
    // а саму отрисовку выкинул из обработчика
    // его дело переменные пересчитывать, а рисовать будет draw
    document.addEventListener("keydown", function pick(e) {
      if(e.keyCode == 87){
        y1-=32;
      }
      if(e.keyCode == 65){
        x1-=32;
      }
      if(e.keyCode == 83){
        y1+=32;
      }
      if(e.keyCode == 68){
        x1+=32;
      }
    });

    по хорошему надо еще, чтоб цифры от времени зависели, ибо requestAnimationFrame будет вызывать вкфц с частотой соответствующей доступному FPS
    Ответ написан
    Комментировать
  • Как сделать десктопное приложение на JS с вызовом кода на php?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    electronjs.org - пишем десктоп на html+css+js
    https://nodejs.org/dist/latest-v10.x/docs/api/chil... или https://nodejs.org/dist/latest-v10.x/docs/api/chil... - для запуска php скрипта из node/electron

    данные из формы можно передать в php через переменные окружения, аргументы процесса или stdin
    Ответ написан
    Комментировать
  • Workers или *** - как сделать скрипт не прекращающий работу при перезагрузке страницы?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    class Pizza {
        constructor() {
            this.crust = prompt('Choose your crust: ');
            this.toppingsCount = +prompt('How many toppings do you want?') || 0;
            this.toppings = [];
        }
    
        makeToppings() {
            const {toppings, toppingsCount} = this;
            for(let i = toppingsCount; i--;) {
                toppings.push(prompt('Choose your topping: '));
            }
        }
    
        makePizza() {
            const {crust, toppings} = this;
            return `Your order is done! You choose ${crust} crust with these toppings: ${toppings.length ? toppings.join(', ') : 'nothing'}`;
        }
    }
    
    let personalPizza = new Pizza();
    personalPizza.makeTopping();
    console.log(personalPizza.makePizza());
    Ответ написан
    1 комментарий
  • Почему не воспроизводится звук через Web Audio API?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У Вас ожидается полная загрузка файла, прежде чем отдать его на воспроизведение, файл очень большой для mp3 и отдается с весьма маленькой скоростью (за 6 минут у меня загрузилось 2.8МБ на инете 100мб/с и файл на этом не закончился).
    Вообще создается ощущение, что там стрим, а не просто файл, тогда ждать воспроизведения Вы будете вообще вечно.
    Вам нужно забирать данные по частям, небольшими порциями и каждую порцию отдавать в sourceBuffer, но не раньше, чем закончится декодинг предыдущей части (очереди в помощь)
    Ответ написан
  • Как получить массив id отмеченных чекбоксов?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const ids = Array.from(element.querySelectorAll('input[type="checkbox"]:checked'), el => el.id);
    Ответ написан
    Комментировать
  • Как сделать такую прокрутку по сайту?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Какой лучший (красивый и короткий) способ проверки на undefined свойства в объекте javascript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Не сочтите за саморекламу, но https://www.npmjs.com/package/@bingo347/fn

    import chain from '@bingo347/fn/mappers/chain';
    import extractField from '@bingo347/fn/mappers/extractField';
    
    // создаем функцию для безопасного извлечения
    const getBCDE = chain(
      extractField('B'),
      extractField('C'),
      extractField('D'),
      extractField('E')
    );
    
    // извлекаем
    const ABCDE = getBCDE(A);
    Ответ написан
    Комментировать
  • Как используя синтаксис ES-2015 class создать экземпляр который был бы функцией?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Полноценно можно сделать только используя Proxy, но работать будет только в окружении ES-2015 (большинство актуальных браузеров уже поддерживают)
    Не полноценно (зато будет работать в браузерах типа IE) - можно сделать через хак предложенный 0xD34F с возвратом своего объекта (функции) из конструктора

    Пример с Proxy:
    const TestClass = (function() {
        class TestClass {
            constructor() {
                this.calls = '';
            }
    
            toString() {
                return this.calls;
            }
        }
    
        Object.setPrototypeOf(TestClass.prototype, Function.prototype);
    
        function callTestClassInstance(el) {
            this.calls += String(el);
        }
    
        return new Proxy(TestClass, {
            construct(TestClass, args) {
                const instance = new TestClass(...args);
                const target = args => callTestClassInstance.apply(instance, args);
                Object.setPrototypeOf(target, TestClass.prototype);
                return new Proxy(target, {
                    apply(target, _, args) {
                        return target(args);
                    },
                    get(_, name) {
                        return instance[name];
                    },
                    set(_, name, value) {
                        instance[name] = value;
                        return true;
                    },
                    has(_, name) {
                        return name in instance;
                    },
                    deleteProperty(_, name) {
                        return delete instance[name];
                    },
                    defineProperty(_, name, descriptor) {
                        return Object.defineProperty(instance, name, descriptor);
                    },
                    getOwnPropertyDescriptor(_, name) {
                        return Object.getOwnPropertyDescriptor(instance, name);
                    },
                    ownKeys() {
                        return Object.getOwnPropertyNames(instance).concat(Object.getOwnPropertySymbols(instance));
                    }
                });
            }
        });
    })();
    Ответ написан
    Комментировать
  • Почему не вызывается функция при 2 запросе к серверу?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Потому что onLoadPage возвращает функцию, которую никто не вызывает, надо так:onLoadPage()(dispatch);
    Ответ написан
  • Как провести A/B тестирование с использованием cookie?

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

    Для google analytics ставьте utm метки в url (можно на js через history API)
    Ответ написан
    Комментировать
  • Почему не работает клонирование canvas?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    А Вы в консоль заглядывать пробовали?
    canvas.clone is undefined
    Ответ написан
    Комментировать
  • Как отследить какие выполняются javascript при загрузки страницы?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В dev-tools Chrome можно повесить брейкпоинт на дом элемент (на изменения атрибутов, на изменения потомков, на удаления). Щелкните правой кнопкой мыши по нужному dom элементу в dom инспекторе, и выберите в меню break on
    Ответ написан
    3 комментария
  • Как отключить скрипт для мобильников?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    подключите такой модуль к проекту:
    const appleDevice     = /iP(hone|od|ad)/;
    const applePhone      = /iPhone/i;
    const appleIPod       = /iPod/i;
    const appleTablet     = /iPad/i;
    const androidPhone    = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i;
    const androidTablet   = /Android/i;
    const windowsPhone    = /Windows Phone/i;
    const windowsTablet   = /(?=.*\bWindows\b)(?=.*\bARM\b)/i;
    const otherBlackberry = /BlackBerry/i;
    const otherOpera      = /Opera Mini/i;
    const otherFirefox    = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i;
    const sevenInch       = /(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)/i;
    
    function match(regex, target = navigator.userAgent) {
        return regex.test(target);
    }
    
    export const isAppleDevice = match(applePhone) || match(appleIPod) || match(appleTablet) || match(appleDevice, navigator.platform);
    export const isAndroidDevice = match(androidPhone) || match(androidTablet);
    export const isWindowsDevice = match(windowsPhone) || match(windowsTablet);
    export const isOtherDevice = match(otherBlackberry) || match(otherOpera) || match(otherFirefox);
    export const isSevenInch = match(sevenInch);
    export const isMobileDevice = isAppleDevice || isAndroidDevice || isWindowsDevice || isOtherDevice || isSevenInch;
    export const isEmulator = isMobileDevice && !isWindowsDevice && (match(/Mac/, navigator.platform) || match(/Win32/, navigator.platform));

    далее импортируйте нужный флаг, и проверяйте через if
    Ответ написан
    Комментировать
  • Require.context and lazy-loading?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://webpack.js.org/api/module-methods/#require...
    обратите внимание на 4й необязательный параметр mode, особенно на 'lazy' и 'lazy-once'
    Ответ написан
    4 комментария
  • Как задать события в классах ES6?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    // мне кажется, что ждать полной загрузки страницы тут незачем
    document.addEventListener('DOMContentLoaded', () => {
        new Slider({
            images: ".slider__galary img",
            btnPrev: ".btnPrev",
            btnNext: ".btnNext",
            rate: false
        });
    });
    
    // хелпер для прослушивания событий
    class EventListener {
        constructor(ctx, handlers, target) {
            this.ctx = ctx;
            this.handlers = handlers;
            Object.keys(handlers).forEach(event => target.addEventListener(event, this));
        }
    
        handleEvent(event) {
            const {handlers, ctx} = this;
            const {type} = event;
            if(typeof handlers[type] !== 'function') return;
            handlers[type].call(ctx, event);
        }
    }
    
    class Slider {
      construnctor({images, btnPrev, btnNext, rate, time = 1000}) {
            this.images = document.querySelectorAll(images);
            this.i = 0;
            new EventListener(this, {
                click: this.prev
            }, document.querySelector(btnPrev));
            new EventListener(this, {
                click: this.next
            }, document.querySelector(btnNext));
            if(rate) {
                setInterval(() => this.next(), time);
            }
        }
        
        prev() {
            this.images[i].classList.remove("showed");
            this.i--;
            if(this.i < 0){
                this.i = this.images.length - 1;
            }
            this.images[i].classList.add("showed");
        }
    
        next() {
            this.images[i].classList.remove("showed");
            this.i++;
            if(this.i >= this.images.length){
                this.i = 0;
            }
            this.images[i].classList.add("showed");
        }
    }
    Ответ написан
    2 комментария
  • Как впустить в поток, поток получаемый из другого сервиса?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    без знания, что за либа предоставляет youtubeApi сделать адекватно проблематично, но можно сделать универсально:
    const {PassThrough} = require('stream');
    
    const youtubeStream = new PassThrough();
    youtubeApi.downloadVideo(
      'v=4P1-JwZF0Vo&t=4519s',
      chunk => youtubeStream.write(chunk),
      () => youtubeStream.end()
    );
    youtubeStream.pipe(res); // где res - выходной поток к клиенту
    Ответ написан
    1 комментарий