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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const sortedArr = arr
        .map(({date, ...rest}) =>
            ({...rest, date: new Date(date)}))
        .sort(({date: a}, {date: b}) =>
            b - a);
    console.log(sortedArr)
    Ответ написан
  • Какие на самом деле типы данных в javascript?

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

    Согласно спеке в JS есть 8 типов данных:
    • object - все объекты и функции (в реальности во всех имплементациях у функций свой тип function)
    • string - строки
    • boolean - логические значения (true и false)
    • number - числа с плавающей запятой двойной точности (в других языках это double или float64)
    • bigint - целые числа (int64) с поддержкой длинной арифметики
    • symbol - спец тип, каждое значение которого уникально
    • undefined - юнит тип с единственным значением undefined, значение по умолчанию во многих случаях
    • null - юнит тип с единственным значением null (в реальности во всех имплементациях null имеет тип object), задумывался и используется как аналог null pointer/null reference в других языках


    Что происходит с типом данных когда str конкатинируется со строкой 'Vova' ?
    с типом данных ничего не происходит. Значение получается новое, по крайней мере так должно быть согласно спеке и так все выглядит для рядового js разработчика.
    На самом деле самый распространенный js движок v8 именно со строками делает под капотом разную магию, зная, что строки никогда не меняются он умеет их представлять в виде массива срезов (множества кусочков лежащих в разных местах), избегая тем самым дорогого копирования памяти. В данном примере result будет состоять из двух срезов, которые указывают на представление кода в памяти, притом первый кусок будет указывать на ту же память что и str. Но если result "доживет" до момента, когда сборщик мусора будет делать дефрагментацию памяти, то после нее он уже будет указывать на целую самостоятельную строку.

    Вопрос вот в чем, так ли примитивы перезаписываются если с ними выполняются какие-то операции? Меня интересует сам алгоритм создания, что происходит внутри
    Примитивы никогда не перезаписываются, по крайней мере пока они "живы" (пока сборка мусора не признает их мусором в виду отсутствия ссылок на память где они лежат). Все манипуляции с переменными под капотом почти всегда (о том когда нет - напишу ниже) являются простыми манипуляциями над указателями (ссылками).

    Являются ли примитивные типы объектами?
    С точки зрения спеки - нет, не являются. У них должны появляться объектные обертки в момент обращения к их полям (через точку или квадратные скобки).
    На деле, если сделать как в спеке - все будет жутко тормозить. Поэтому в v8 почти все является объектом (правда не совсем таким, как мы видим объекты со стороны js), а соблюдение спеки для примитивных типов достигается через иммутабельность.
    Исключением являются null и undefined, у которых нет ни полей, ни прототипа. Для них хранится только информация о типе.
    Так же после оптимизаций jit компилятора числа могут избавится от объектных оберток, когда оптимизируемый код их не использует, тем самым избавляясь от разыменовывания указателя, при этом bigint может превратится в int64, а number в float64 или int32 в зависимости от использования. Так же, массивы состоящие только из чисел одного типа могут быть сведены к настоящим массивам из чисел, но этого эффекта можно достичь и до оптимизаций, если использовать типизированные массивы.
    Ответ написан
    3 комментария
  • Как при нажатии на select > option открыть элемент?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://developer.mozilla.org/en-US/docs/Web/API/H...
    Нужно отслеживать change на select
    option, на сколько помню, вообще не кидают событий
    Ответ написан
    Комментировать
  • Как сделать обработку жеста "зум двумя пальцами" на тачскринах на JavaScript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Можно и без библиотек:
    https://developer.mozilla.org/ru/docs/Web/API/Touc...
    https://developer.mozilla.org/ru/docs/Web/API/Touc...
    https://developer.mozilla.org/ru/docs/Web/API/Touc...
    https://developer.mozilla.org/en-US/docs/Web/API/T...

    В TouchList каждый элемент - это палец. По изменениям координат в последовательных события touchmove можно построить векторы движения.
    Усредняем эти векторы до 1/4 или 1/8 долей окружности с общим центром для всех векторов, если 2 пальца движутся в противоположных долях - это зум, навстречу друг другу - уменьшение, а от друг-друга - увеличение.
    Ответ написан
    Комментировать
  • Как работать с IndexedDB из класса?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://developer.mozilla.org/ru/docs/Web/JavaScri...
    100 раз уже это спрашивали...
    Научитесь работать с асинхронным кодом...
    Ответ написан
  • JS выдает разный контекст при разном способе вызова функций, как с этим работать?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://developer.mozilla.org/ru/docs/Web/JavaScri...

    addEventListener, кстати, может принимать не только функции, но и объекты с методом handleEvent, и в нем this будет указывать на переданный объект
    https://developer.mozilla.org/ru/docs/Web/API/Even...
    Ответ написан
    Комментировать
  • Какое практическое применение для функции генератора?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Генератор - это императивно управляемый итератор. Сами итераторы позволяют производить ленивые вычисления.

    Практическое применение например в том, что можно построить высокоуровневые абстракции над итераторами:
    function* counter() {
      let i = 0;
      while (true) {
        yield i++;
      }
    }
    
    function* map(innerIterator, f) {
      for (const value of innerIterator) {
        yield f(value);
      }
    }
    
    function* filter(innerIterator, f) {
      for (const value of innerIterator) {
        if (f(value)) {
          yield value;
        }
      }
    }
    
    function* take(innerIterator, count) {
      let i = 0;
      for (const value of innerIterator) {
        yield value;
        if (++i === count) { return }
      }
    }
    
    function* inspect(innerIterator) {
      for (const value of innerIterator) {
        console.log(value);
        yield value;
      }
    }
    
    console.log('Создаем итератор');
    const iter = inspect(
      take(
        map(
          filter(
            counter(),
            v => v % 2 === 0
          ),
          v => v * 2
        ),
        30
      )
    );
    console.log('Итератор есть, но он еще ничего не считает: ', iter);
    console.log('Вычисления будут по требованию:');
    console.log([...iter]);
    Ответ написан
  • Чем JavaScript абстрактнее других языков программирования?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    На JS можно спокойно писать (и очень многие пишут) вообще не задумываясь где и как у Вас выделяется память и где и когда она освобождается. И программа будет работать, возможно даже без багов и утечек.

    В JS Вам не нужно думать, о том сколько живут объекты, если у Вас есть ссылка - объект точно жив.

    В JS Вам не нужно думать, какой у Вас сейчас диспатчинг - статический или динамический (он всегда динамический - более дорогой, но гибкий), а если диспатчинг все же динамический, то не нужно думать, а какая здесь будет использована таблица виртуальных функций.

    В JS у Вас никогда не будет Undefined Behavior.

    В JS у Вас никогда не будет гонок данных, каждый поток (воркер) живет в своем пространстве памяти. И даже если Вы пошарите память, Вам не придется парится с атомиками/мьютексами и c memory order, все уже решили за Вас.

    В C++ Вам придется об этом всем думать, если захотите написать что-то полезное.
    Ответ написан
    2 комментария
  • Как правильно присвоить класс?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const mediaQuery = window.matchMedia('(max-width: 992px)');
    const handler = () => 
        $(document.body).toggleClass('lock', mediaQuery.matches);
    mediaQuery.addListener(handler);
    handler();

    https://developer.mozilla.org/ru/docs/Web/API/Wind...

    А вообще, такое спокойно через CSS можно делать:
    @media (max-width: 992px) {
        body {
            /* тут то что у Вас в .lock было */
        }
    }
    Ответ написан
    2 комментария
  • Как распарсить readbleStream, чтобы получить из него файл?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://nodejs.org/dist/latest-v14.x/docs/api/stre...
    https://nodejs.org/dist/latest-v14.x/docs/api/stre...

    Но в Вашем примере уже присутствует pipe, который сам вычитывает readable поток в writable (в Вашем случае res)
    https://nodejs.org/dist/latest-v14.x/docs/api/stre...

    Поток штука одноразовая, 2 раза прочитать не получится, благо с обычными файлами никто не мешает открыть любое количество потоков.
    Ответ написан
    Комментировать
  • Как в java script представить строку вида "level1[level2][level3]" в массив/объект/map с соответственной вложенностью?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Придется парсить ключи в обработчике submit:
    const re = /(.+)\[(.+)\]\[(.+)\]/;
    const formData = new FormData(drawingForm);
    const result = {};
    for (const [key, value] of Object.entries(formData)) {
        const matches = key.match(re);
        if (!matches) { continue }
        const [, k1, k2, k3] = matches;
        ((result[k1] ??= {})[k2] ??= {})[k3] = value;
    }
    console.log(result); // тут валидация
    Ответ написан
    1 комментарий
  • Как разобраться с rpc запросами на основе TL-схемы?

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

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

    В VAST могут быть параметры для VPAID, но он не обязан их использовать. Он может сходить за рекламой на свой сервер, который ему заранее известен, или вообще воспроизводить рекламу, которая в него зашита.

    А может и не рекламу крутить, я например как то делал в виде VPAID интерактивную вакансию и таргетировал ее на IT'шников через рекламные сети.
    Ответ написан
    Комментировать
  • Как реализовать цикл на JS?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У Вас функции popup1, popup2 и popup3 ничего не возвращают
    if (popup1() === random)соответственно здесь строго сравнивается undefined с числом, что всегда даст false.

    Вангуя следующий вопрос, сразу намекну, что prompt возвращает строку, и ее тоже так в лоб с числом не сравнишь.

    Ну и напоследок:if (agreement === true)зачем === true в условии, если agreement всегда типа boolean?
    Ответ написан
    1 комментарий
  • Как вытянуть ключ с обьекта который находится в массиве?

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

    Еще одна проблема, хоть она и не относится к вопросу, это то что у Вас присутствует бесполезная работа с localStorage (Вы каждый раз пишите туда новые, никак не зависящие от старых, данные, только ради того чтоб их тут же прочитать), а так же бесполезная сериализация/десериализация JSON.
    Отношение к пользовательским ресурсам - все равно что вломится к пользователю домой и плюнуть ему в лицо.
    Ответ написан
    Комментировать
  • Как сохранять события в localStorage js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    localStorage.getItem сам не поставит класс элементу, он просто читает значение
    if (localStorage.getItem('theme') !== null) {
        localStorage.getItem('theme') // эта строка ничего не делает
    }


    Попробуйте так:
    (function () {
      const blue = document.querySelector('#pink')
    
      switch (localStorage.getItem('theme')) {
          case 'blueTheme':
              blue.classList.add('blueTheme')
      }
    
      blue.addEventListener('click', () => {
        if (blue.classList.contains('blueTheme')) {
            blue.classList.add('blueTheme')
            localStorage.setItem('theme', 'blueTheme')
        } else {
            blue.classList.remove('blueTheme')
            localStorage.removeItem('theme')
        }
      })
    }())
    Ответ написан
    Комментировать
  • В чем разница двух конструкций в js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    $(function() {
    
    });
    вызывает функцию $ и отдает ей анонимную функцию в качестве аргумента

    (function($) {
    
    })(jQuery);
    Вызывает анонимную функцию сразу, параметр jQuery попадет в аргумент $ внутри функции
    Ответ написан
    Комментировать
  • В этом случае объект очищается по причине работы алгоритма Mark-and-sweep или это просто эффект работы локальной переменной...?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Все сильно зависит от движка, но в основном принципы похожи. Расскажу на примере v8 (chrome, node).
    Первое, что надо понять, в v8 сборка мусора основана на поколениях. И в разных поколениях применяются разные алгоритмы. В v8 используется 3 поколения:
    - Молодое (собирается по наполнению (часто), но быстрым упрощенным алгоритмом)
    - Старое (собирается по расписанию (редко), здесь как раз Mark & Sweep)
    - Особое (я не очень про него знаю, здесь очень большие объекты + объекты с прямым доступом из глобального)

    Второе, что нужно понять, все данные доступные из JS v8 хранит на куче, независимо примитив это или js-объект. С точки зрения GC все есть объект, и числа и строки и функции.

    Теперь более подробно про молодое поколение. Его цель - быть быстрым, быстро выделять и освобождать память. Создатели v8 прекрасно знают, что аллокация на куче - крайне затратная операция, поэтому здесь преаллоцированы 2 страницы памяти, которые используются по очереди. Заодно можно получить бонус в работе с процессорным кэшем, за счет того, что здесь "горячие" данные и они лежат рядом, а значит попадут на одну кэш линию. Когда мы создаем новый объект, v8 просто помещает его в конец активной страницы. Если места не хватает происходит быстрая сборка мусора. А еще здесь используется подсчет ссылок (он быстрее), но только для ссылок из старого поколения - если есть хоть 1 такая ссылка - объект живой, а так же живо все его объектное дерево. Так же нельзя "убивать" объект, если на него есть ссылки из стэка. Все остальное "мертвое". Живые объекты переносятся в начало второй страницы памяти (заодно происходит дефрагментация памяти), после чего она становится активной. Если объект пережил 3 таких быстрых сборки, то вместо второй страницы его переносят на старое поколение, при этом происходит аллокация памяти.

    В Вашем примере задействовано только молодое поколение.
    function f() {
        // это мертвый код, после оптимизации f строка вообще не будет память использовать
        let a = 'some text';
    
        // это 2 молодых объекта, на них уже ссылается контекст вызова f, а на него ссылается стэк
        var obj1 = {};
        var obj2 = {};
        obj1.p = obj2; // obj1 references obj2
        obj2.p = obj1; // obj2 references obj1. This creates a cycle.
    
        // при завершении функции стэк перестает ссылаться на контекст вызова
        // контекст вызова умрет при ближайшей GC,
        // а вместе с ним и obj1 и obj2, так как их никто не отметит "живыми"
    }
    f();
    Ответ написан
    Комментировать
  • Как получить промисо-завершающий callback от асинхронной функции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если правильно понял замысел, то можно как-то так:
    async function test() {
        let savedResolve, sevedReject;
        const promiseForReturn = new Promise((resolve, reject) => {
            // этот колбэк отрабатывает синхронно
            sevedResolve = resolve;
            savedReject = reject;
        });
        // поэтому savedResolve и sevedReject уже доступны здесь
        sevedReject(1);
        return promiseForReturn; // промис возвращаемый test() будет связан с этим и ждать его
    }

    Но лучше с таким все же быть аккуратным
    async function test() {
        let savedResolve, sevedReject;
        const promiseForReturn = new Promise((resolve, reject) => {
            sevedResolve = resolve;
            savedReject = reject;
        });
        // это deadlock
        await promiseForReturn;
        sevedResolve(1);
    }
    Ответ написан