Ответы пользователя по тегу JavaScript
  • Почему с let работает а с var нет?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У var область видимости функции, на каждой итерации цикла мы имеем дело с одной и той же переменной.
    У let - область видимости блока, на каждой итерации цикла новая переменная
    Ответ написан
    4 комментария
  • Зачем нужны set, get?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ну вот из самого простого, что нельзя сделать с функцией, но можно с get/set:
    obj.field++;
    obj.field += 5;
    const variable = obj.field = 10;


    Или еще пример, вот было у нас
    const human = {
      name: 'Andrew'
    };
    Мы уже в коде много где использовали это поле как поле, и вдруг понадобилось делать что-то, когда это поле меняется, что проще, сделать сеттер или поменять весь остальной код?
    Ответ написан
    Комментировать
  • Как сделать выполнение php кода, когда пользователь закрыл вкладку?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Посылать запросы на unload/beforeunload события, как рекомендует Алексей Николаев - не очень хорошая идея
    Асинхронный запрос будет оборван в произвольное время, и может не дойти до сервера. Синхронный - заблокирует вкладку и создаст неприятный пользовательский опыт.

    Специально для таких случаев есть navigator.sendBeackon, который работает асинхронно, но не обрывается при закрытии вкладки (даже если сервер будет держать запрос пол часа - будет работать все ок, я проверял)
    Правда если нужна поддержка IE или старых сафари (iOS10 и старее), то все же придется вернутся к синхронным запросам для этих браузеров
    Ответ написан
    Комментировать
  • Как сделать vast рекламу html5?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В спеке более чем разжевано как сделать:
    https://www.iab.com/wp-content/uploads/2015/06/VAS...

    Сам VAST - не более чем xml с данными, если не нужна поддержка VPAID - сделать можно за 1 вечер буквально.
    Ответ написан
    Комментировать
  • Как написать асинхронный jest тест для action // mobx?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Во-первых, addItem ничего не возвращает, естественно нельзя вызвать у ничего (undefined) метод then, так как у undefined в принципе не может быть методов. Нужно добавить return:
    addItem = text => {
               return axios.post("/task", {
                   headers: { "Content-Type": "application/json" },
                   text: text
                 })
                 .then(res => {
                   this.arr.push(res.data.task);
                 })
                 .catch(e => console.log(e));
             };

    Во-вторых, у jest для промисов есть конструкция resolves
    describe("STORE", () => {
      it("create new task", () => {
        const store = new Store();
        const text = "test";
        expect(store.addItem(text)).resolves.toBe(1);
      });
    });

    И да, тест будет вполне законно провален, причина опять таки в return, но с этим я уже предлагаю разобраться самостоятельно
    Ответ написан
    1 комментарий
  • Как добавить класс когда элемент появляется в область видимости?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вот этоvar m_top = $('.go').offset().top;запомнит оффсет только для самого первого элемента найденного по селектору, поэтому и обрабатывается только он.
    Использовать событие scroll для отслеживания вьюпорта - это наплевательское отношение к ресурсам пользователя, ведь есть более эффективное апи для этого - IntersectionObserver
    Пример:
    $(document).ready(function(){
      var observer = new IntersectionObserver(function(entries){
        entries.forEach(function(entry){
          if(entry.isIntersecting) {
            $(entry.target).addClass('active bounceInLeft');
          } else {
            $(entry.target).removeClass('active bounceInLeft');
          }
        });
      }, {threshold: 0.1});
      $('.go').each(function(){
        observer.observe(this);
      });
    });

    Если нужен IE или Safari старее 12, то вот полифил: https://www.npmjs.com/package/intersection-observer
    Ответ написан
    Комментировать
  • Как в Vue в методе вызвать другой метод?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Как сформировать объект в виде ассоциативного массива?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Да. В каждой форме по 3 элемента
    const arr = $('.filter').serializeArray();
    const result = [];
    for(let i = 0; i < arr.length; i += 3) {
      result.push(arr.slice(i, i + 3).reduce((acc, {name, value}) => ({...acc, [name]: value}), {}));
    }
    Ответ написан
    1 комментарий
  • Как получить колбек загрузки внешнего скрипта?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если сторонняя библиотека посылает xhr/fetch запрос, то перехватить его со страницы невозможно никак, разве что обернуть соответствующее апи до загрузки этой библиотеки.
    Если это именно вставка скрипта, то у скрипт элемента есть события load и error связанные с загрузкой, можете подписаться на них. Тут задача уже, как поймать добавление конкретного тега скрипт, думаю MutationObserver прекрасно справится с этой задачей.
    Более подробных советов без кода и понимания, что происходит на странице, тут не дашь
    Ответ написан
    Комментировать
  • В чем практические отличия null от undefined?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    undefined - имеет отдельный тип данных, при том это юнит-тип (имеет единственное значение). Кроме того, это значение по умолчанию для неинициализированных переменных, непереданных аргументов, результата функции, которая ничего не вернула и отсутствующих полей объектов (включая цепочку прототипов), а так же this по умолчанию (с es5). У undefined нет своего литерала, но есть неизменяемая (с es5) глобальная переменная. Кроме того undefined можно получить из оператора void. Забавно, что в v8 это единственный не ссылочный тип данных, а в памяти хранится только тэг типа.
    null - по спеке тоже должен иметь свой юнит-тип, но абсолютно во всех реализациях он имеет тип object. В отличие от undefined, null - это ссылка, а значит в памяти будет тэг типа + указатель. В v8 этот указатель ведет на static память, поэтому любой null всегда равен любому другому null, даже из другого контекста, что соответствует спеке.
    Ответ написан
  • Как правильно работать с двумя массивами одновременно?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ну во-первых, querySelectorAll возвращает коллекцию NodeList а не массив, это важно понимать.
    Во-вторых, у NodeList нет сеттера onclick в отличии от элементов, а следовательно Ваше присваивание туда функции просто не сработает.
    В-третьих, не стоит пользоваться сеттерами вида oneventname, так как это чревато проблемами, используйте метод addEventListener
    В-четвертых, querySelectorAll можно использовать не только на document, но и на элементах
    В-пятых, в обработчик события приходит объект события в качестве аргумента, в котором есть свойство target - элемент на котором событие произошло

    По-итогу:
    function listener(event) {
      const target = event.target.closest('.app__item');
      target.querySelectorAll('.equalizer').forEach(
        elem => elem.style.display = 'block'
      );
      // так как дальнейшие клики будут гонять бесполезный цикл, то лучше отписаться
      target.removeEventListener('click', listener);
    }
    document.querySelectorAll('.app__item').forEach(
      item => item.addEventListener('click', listener)
    );
    Ответ написан
    Комментировать
  • Можно ли поместить(записать) переменные в массив?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В js многие операторы не являются выражением, и как следствие их можно использовать только как statement.
    Среди них var, let, const, return, throw (есть пропозал, так что в будущем может изменится), if, for, while и некоторые другие.
    следовательно написать x = delete y.z можно, так как оператор delete - является выражением и возвращает true или false
    а написать x = var y нельзя, так как var ничего не возвращает, даже undefined не вернет.

    можно так:
    var arrey = [];
    var a = 1;
    var b = 2;
    arrey[0] = a;
    arrey[1] = b;

    но правильнее так:
    var arrey = [];
    var a = 1;
    var b = 2;
    arrey.push(a, b);
    или так:
    var a = 1;
    var b = 2;
    var arrey = [a, b];
    Ответ написан
    Комментировать
  • Как передать элемент в callback функцию?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Передавать его еще одним аргументом в loadScript
    let loadScript = (url, callbackScript, elem) => {
        let script = document.createElement('script');
        script.src = url;
        document.getElementsByTagName('body')[0].append(script);
        script.onload = function() {
          callbackScript(elem); // Как в эту функцию передать elem? elem находится снизу при обходе массива
        };
      };
    App.prototype.initModule = function(array) {
        array.forEach(elem => {
          loadStyles.call(DATA, DATA[elem].styleURL); // Вот здесь передаю callback
          loadScript.call(DATA, DATA[elem].scriptURL, callback, elem);
        });
      };


    P.S. метод call не имеет смысла для стрелочных функций, ибо у них нет своего this
    Ответ написан
    2 комментария
  • Можете объяснить для нужна опция body в Fetch?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://developer.mozilla.org/ru/docs/Web/API/Requ...
    В запросе - это тело запроса, может быть строкой, Blob, ArrayBuffer или FormData

    https://developer.mozilla.org/en-US/docs/Web/API/R...
    В ответе - Readable Stream с телом ответа
    Так же в ответе есть методы для чтения и парсинга тела возвращающие промис
    https://developer.mozilla.org/en-US/docs/Web/API/R...

    Сам fetch принимает или объект запроса или url и параметры запроса, то есть body там как у запроса
    Ответ написан
    Комментировать
  • Как написать функцию для валидации CSS кода?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    1. Распарсить текст в токены
    2. Построить из токенов AST
    Если оба шага успешны - true, если хоть где-то не вышло - false
    Семантика есть в официальной спеке
    Ответ написан
    1 комментарий
  • Как упростить этот javascript код?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const content = document.body.querySelector('.editer');
    const htmlTags = content.getElementsByTagName("*");
    const navs = []; // здесь let не нужен
    
    for(let i = 0; i < htmlTags.length; i++) {
      const htmlTag = htmlTags[i];
      const lastNav = navs[navs.length - 1]; // resH2 всегда будет таким (см. комменты ниже)
      const lastChildOfLastNav = lastNav && lastNav.children[lastNav.children.length - 1]; // resH3 всегда будет таким
      switch(htmlTag.localName) {
      case 'h2':
        setID(htmlTag, i);
        addItem(navs, htmlTag);
        break;
      case 'h3':
        setID(htmlTag, i);
        // тот find что у Вас всегда найдет последний элемент если он есть, не зачем гонять лишний цикл
        if(lastNav) {
          addItem(lastNav.children, htmlTag);
        }
        break;
      case 'h4':
        setID(htmlTag, i);
        // опять же был лишний цикл ради последнего элемента, да еще и в него вложен такой же
        if(lastChildOfLastNav) {
          addItem(lastChildOfLastNav.children, htmlTag);
        } else if(lastNav) {
          addItem(lastNav.children, htmlTag);
        }
        break;
      }
    }
    
    function addItem(obj, {innerText: name, id}) {
      obj.push({
        name,
        id,
        children: []
      });
    }
    
    function setID(htmlTag, i) {
       htmlTag.setAttribute('id', `nav-${i}`);
    }
    Ответ написан
    Комментировать
  • Серия книг "You dont know js" - стоит ли начинать читать?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Есть ли смысл начинать читать её сейчас, или на сегодняшний день она уже слишком устарела?
    Фундаментальные знания не устаревают никогда, а в данной книге именно фундамент.
    насколько я понимаю, написана она опираясь на старый стандарт
    Даже оператор with, который deprecated начиная с es5 можно использовать в самом современном движке js. Каждая новая версия ES лишь дополняет предыдущую, но не отменяет ее, хотя некоторые вещи и становятся нежелательными (вроде использования var после появления let и const), новые вещи основываются на старых (иначе бы babel не работал). Ну а то немногое, что совсем deprecated (вроде оператора with или глобального объекта в качестве this по умолчанию) - как правило плохие практики и в таких книгах почти не освещаются
    Ответ написан
    Комментировать
  • Почему не работает autoplay в Plyr на мобильках?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Play со звуком возможен только синхронно после действия пользователя (клик мыши, нажатие кнопок клавиатуры).
    Проверить, что событие инициировано пользователем можно с помощью event.isTrusted
    Autoplay можно запустить без звука, притом на медиа элементе (теги video, audio) должно быть именно mediaEl.muted = true, а mediaEl.volume = 0 не поможет
    Десктопные браузеры тоже могут блокировать воспроизведение со звуком, но применяют другие политики, например используется статистика (общая и персонально пользователя) для выявления адекватных сайтов с автовоспроизведением (например ютуб и яндекс видео скорее всего запустятся у всех без особых проблем, т.к. пользователи очень часто запускают на них видео)
    Ответ написан
    Комментировать