• Как правильно описать тип в typesctipt?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Все дело в том, что тип profileActionsType - это discriminated union
    Поле post присутствует лишь в одном из его подтипе, соответственно извлечение этого поля из полного типа - с точки зрения typescript - ошибка.
    Проверка на конкретное значение поля type вполне сойдет за type guard, который ts поймет.

    P.S. размещение кода картинками запрещено правилами сервиса
    Ответ написан
  • Устарел ли getElementsBy* и чем лучше querrySelector?

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

    Говорить о том, что некие фичи устарели - крайне глупо, если знать, что они ведут себя иначе, чем более модные альтернативы. Предлагаю немного разобраться и начать с того что на поверхности:
    - getElementById и querySelector возвращают конкретную ноду в единственном экземпляре
    - querySelectorAll и getElementsByName возвращает статичную коллекцию NodeList
    - getElementsByClassName, getElementsByTagName и getElementsByTagNameNS возвращают динамическую коллекцию HTMLCollection
    Как видим результат у разного апи различен, а значит и говорить, что некоторые из них устарели - глупо.
    Правда тут есть забавный момент
    в спеке HTMLCollection отмечен как "исторический артефакт", который не стоит использовать при проектировании нового апи. Но заметка эта не для веб-разработчиков, а для тех кто проектирует новое DOM апи.

    С устареванием вроде разобрались, но в вопросе еще есть часть "чем лучше". И тут есть теория, что getElementsBy* быстрее querySelector*. Чисто теоретически звучит логично, querySelector* должен делать полный поиск по дереву со сложностью O(n), а getElementsBy* могут использовать индексы на базе HashMap и получать данные со сложностью O(1), тут и особенности HTMLCollection будут кстати, так как можно не копировать коллекцию, а отдавать одну и ту же (и браузеры действительно так делают). Но без пруфов теория так и останется теорией.
    И бенчмарки - так себе пруф
    Хотя направлять инвесторов в нужную сторону - самое то. Проблема бенчмарков, что можно написать их так, что любая из сравниваемых сторон заметно обгонит другую. Дело техники. Например BubbleSort с O(n2) при определенных условиях в чистую уделывает MergeSort и QuickSort с их O(n×log2n), а именно при n=20 или меньше, 400 простых memswap в наглую рвут 87 рекурсивных операций с memcpy внутри
    Гораздо лучше тут выглядят исходники. И я выбрал исходники chromium, как самого распространенного:
    - getElementsBy* методы все как один обращаются к некой шаблонной функции EnsureCachedCollection, которая в свою очередь обращается к некоему NodeLists кэшу, устроенному внутри действительно как HashMap или что-то наподобие. Никакого поиска тут нет, просто берутся готовые значения, сложность у всего этого действительно константная O(1).
    - querySelector* используют абстракцию SelectorQuery, которая и в самом деле делает поиск по DOM. Но данный поиск неплохо оптимизирован и обвешан кэшами. Притом CSSOM использует абсолютно тот же алгоритм поиска DOM нод для каждого селектора в css.
    Для примера
    в подключенных на странице этого вопроса стилях более 1600 правил (некоторые из которых потенциально могут содержать несколько селекторов), полная обработка стилей из этого файла заняла на моей машине (Ryzen 3600 в стоке) чуть больше 9 мс. Если все это немного округлить, то понадобится 15000 querySelectorAll подряд, притом с разными селекторами, чтоб был промах кэша, дабы я ощутил заметную глазу задержку в ~100мс


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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Данная задача в принципе не решается сортировкой, так как сортировка это про отношение больше/меньше/равно, которого в данном случае нет.
    Самое простое здесь, это построить из этих элементов двусвязный список, а затем преобразовать его в результирующий массив:
    function orderArray(arr) {
      // для начала построим ноды списка и соберем их в 2 HashMap по обоим строкам
      const maps = arr.reduce((acc, item) => {
        const node = {item, next: null, prev: null};
        acc[0][item[0]] = node;
        acc[1][item[1]] = node;
        return acc;
      }, [{}, {}]);
    
      // после пройдемся по обоим HashMap и соединим связи
      for(const key of Object.keys(maps[0])) {
        maps[0][key].next = maps[0][maps[0][key].item[1]] || null;
      }
      for(const key of Object.keys(maps[1])) {
        maps[1][key].prev = maps[1][maps[1][key].item[0]] || null;
      }
    
      // найдем начальную ноду списка (ноду без предыдущей ноды)
      let cur = Object.values(maps[0]).find(({prev}) => prev === null);
    
      // и начиная с нее соберем список в массив
      const result = [];
      while(cur) {
        result.push(cur.item);
        cur = cur.next;
      }
    
      return result;
    }
    
    console.log(orderArray([['butter', 'jelly'], ['bananas', 'apples'], ['peanuts', 'butter'], ['jelly', 'bananas']]));
    Ответ написан
    1 комментарий
  • Могу ли я в чистом javascript в асинхронной функции подождать возникновения события?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Первое что нужно понимать, что async/await - это всего лишь синтаксический сахар над промисами, а значит имеет все особенности работы с ними:
    Во-первых, промис может разрешится (или отклонится, но в этой задаче reject не нужен) только единожды. Это сильно отличает их от событий, которые могут происходить многократно.
    Во-вторых, промисы обрабатываются на особой фазе event loop называемой microtasks, что опять же отличается от событий, которые выполняются на другой фазе (tasks). Это означает, что обработка промиса (колбэк метода then, или сахар над ним в виде await оператора) всегда произойдет асинхронно от возникновения события. Это накладывает ряд ограничений, например не получится сделать preventDefault у объекта или не получится запустить действия требующие синхронной работы из trusted события (play не muted video/audio, вход в фулскрин и тд).

    В простом варианте можно слушать событие разово, для чего можно использовать параметр once. Так же для оптимизации можно использовать параметр passive, так как нам все равно поздно вызывать preventDefault, а в некоторых случаях это может дать нам оптимизацию. Ну и управлять параметром capture попросту бесполезно, так как обработка будет в любом случае после обеих фаз. В итоге для этого можно пользоваться такой функцией хелпером:
    function listenOnce(target, event) {
        return new Promise(resolve => {
            target.addEventListener(event, resolve, {
                once: true,
                passive: true
            });
        });
    }
    
    // использование
    const event = await listenOnce(document, 'DOMContentLoaded');
    console.log(event);


    Если же нужно слушать событие многократно, то разумно обернуть прослушивание события в асинхронный итератор. Здесь так же присутствуют все ограничения связанные с промисами, но за счет того, что у нас будет итератор по множеству промисов, мы сможем слушать событие многократно. так же тут нужно предусмотреть возможность отписаться от события. Хелпер для данного случая получится такой:
    function listen(target, event) {
        let currentResolve = () => {};
        const handler = event => currentResolve({value: event, done: false});
        return {
            [Symbol.asyncIterator]() {
                target.addEventListener(event, handler, {passive: true});
                return {next: () => new Promise(resolve => {
                    currentResolve = resolve;
                })};
            },
            stop() {
                target.removeEventListener(event, handler);
                currentResolve({done: true});
            }
        };
    }
    
    // использование
    for await(const event = listenOnce(window, 'scroll')) {
        console.log(event);
    }
    
    // с отпиской
    const eventIterator = listenOnce(window, 'scroll');
    let count = 10;
    for await(const event = eventIterator) {
        console.log(event);
        if(--i === 0) {
            eventIterator.stop();
        }
    }
    Ответ написан
    4 комментария
  • Можно ли перенести настоящий проц и видюху в виртуальную машину?

    bingo347
    @bingo347
    Crazy on performance...
    Проц пробросить не получится, хостовая ОС монопольно владеет им. Но в современном x86 есть технологии Intel VT и AMD-V (в зависимости от производителя проца), которые позволяют предоставлять прямой доступ к ресурсам процессора в гостевую ОС. Данные технологии доступны в большинстве виртуальных машин с x86 на хосте и x86 в госте. Однако эмулировать так ARM на x86 или наоборот не выйдет, все таки разные архитектуры.

    Насчет видюхи и других PCIe устройств. Их можно только полностью передать в гостевую ОС, и они станут недоступны в хостовой ОС (если так же нужно изображение на хосте, то понадобится 2 видяхи, и 2 монитора, ну или VNC/RDP сервер вместо монитора). Еще одно ограничение, что сделать это могут только гипервизоры работающие в пространстве ядра хостовой ОС (VirtualBox работает в пользовательском пространстве, а вот KVM может, так как работает как модуль ядра Linux, Hyper-V (если нужна винда на хосте) тоже вроде может, но я не уверен)
    Ответ написан
    3 комментария
  • Стили abc в vs code?

    bingo347
    @bingo347
    Crazy on performance...
    1. Скачать или клонировать исходники VS Code
    2. Поправить по своему вкусу здесь: https://github.com/microsoft/vscode/blob/master/ex...
    3. Собрать
    Ответ написан
    Комментировать
  • Почему функции могут не работать?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    + к ответу WbICHA:
    yp += speed;
    какого поведения Вы ожидаете от присваивания в аргумент?
    Ответ написан
    8 комментариев
  • Можно ли код babel конвертировать обратно?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    class Dropdown() {
      constructor(selector) {
      	this.$el = document.querySelector(selector);
      }
    
      toggle(cls) {
      	this.$el.classList.toggle(cls);
      }
    }
    
    class Nav extends Dropdown {
      constructor(selector) {
      	super(selector);
      	this.$btn = this.$el.querySelector('.nav-button');
        	this.$btn.addEventListener('click', this.toggle.bind(this, 'nav_open'));
      }
    }
    
    class Menu extends Dropdown {
      constructor(selector) {
      	super(selector);
      	this.$btn = this.$el.querySelector('.menu-button');
        	this.$btn.addEventListener('click', this.toggle.bind(this, 'menu_open'));
      }
    }
    
    new Nav('.nav');
    new Menu('.menu');
    так?
    Ответ написан
    2 комментария
  • Как правильно вывести такой код в innerHtml?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    // небольшая функция хелпер, чтоб писать меньше кода:
    const appendNewDiv = parent => parent.appendChild(document.createElement('div'));
    
    // создадим основные эллементы
    const wrap = appendNewDiv(albumTrack);
    const title = appendNewDiv(wrap);
    const itemAlbumWrap = appendNewDiv(wrap);
    const itemAlbum = appendNewDiv(itemAlbumWrap);
    
    wrap.classList.add('album__item');
    title.classList.add('album_title');
    itemAlbumWrap.classList.add('album__item__wrap');
    itemAlbum.classList.add('album__photo');
    
    // сюда будем складывать элементы, которые должны удалятся при смене number
    let elements = [];
    
    // функция, через которую меняем отображаемые данные по number
    const renderByNumber = number => {
        const {albumId, albums} = arr2[number];
        elements.forEach(e => wrap.removeChild(e));
        title.textContent = `Альбом ${albumId}`;
        elements = albums.map(album => {
            const e = appendNewDiv(wrap);
            e.textContent = album.title;
            return e;
        });
    };
    
    // при изменении number теперь просто вызываем
    renderByNumber(number);
    Ответ написан
    3 комментария
  • Как использовать метод static внутри класса через this?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Все прекрасно работает:
    https://www.typescriptlang.org/play?#code/MYGwhgzh...

    Вероятно дело в том, что скобки в вызове метода забыли
    Ответ написан
  • Что вообще происходит с современным софтом?

    bingo347
    @bingo347
    Crazy on performance...
    В современных реалиях никто не думает про завтра, все озабочены как срубить побольше бабла сегодня. Это очень сильно бьет по качеству, ибо качество - это долго и дорого, что вот никак не сопоставимо ни с "сегодня" ни с "побольше бабла".
    Добавьте сюда, что разработчиков, умеющих включать мозг и писать что-то адекватное, катастрофически мало, на всех не хватает попросту. А еще они непомерно много денег хотят, что большинству стартапов тупо не по карману. Да и зачем искать адекватного разработчика, когда за те же деньги можно нанять 10-20 макак фреймворкопользователей, притом найм всех 20 займет времени гораздо меньше, чем 1 адекватного. И опять приходим к тому, что можно дешевле и сегодня, но абы как, зато продукт есть.
    Ответ написан
    Комментировать
  • Как округлить число в Javascript до N знаков после запятой?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Отсортировать массив и вернуть bolean?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const isSorted = arr => arr.every((el, i) => {
      if(i === 0) { return true; }
      const prev = arr[i - 1];
      const elType = typeof el;
      const prevType = typeof prev;
      if(elType === prevType) {
          return el >= prev;
      }
      return elType === 'string' && prevType === 'number'
    });
    isSorted([0, 1, 2, 2, 2, 3, 'a', 'b', 'w']); // true
    isSorted([0, 3, 1, 2, 2, 2, 'a', 'b', 'w']); // false
    isSorted(['a', 1, 2, 2, 2]); // false
    isSorted([1, 2, 2, 0, 'a']); // false
    Ответ написан
  • Почему не выполняется every?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У HTMLCollection нет метода every, и метода includes тоже нет, как и метода some у DOMElement
    Ответ написан
    7 комментариев
  • Является ли строка выражением?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Является.
    Все что можно присвоить в переменную, вернуть из функции, передать в другую функцию - выражение.
    Ответ написан
    Комментировать
  • Как сделать команды с "похожим" текстом?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Если набор возможных команд небольшой, то расстояние левенштейна Вам подойдет, с какой командой расстояние минимально - ту и подразумевал пользователь, ну и стоит вести некое пороговое значение, если все команды "дальше" этого значения, то введена бессмыслица
    Ответ написан
    Комментировать
  • Как методы вроде foreEach передают аргумент в callback функцию?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать