Задать вопрос
  • Какой язык поможет научиться грамотно подходить разработке на БЭ?

    bingo347
    @bingo347
    Crazy on performance...
    Хотите, чтоб компилятор бил по рукам за почти любые грехи - попробуйте Rust, хорошие практики он Вам точно привьет, а там глядишь, пока изучаете эти самые практики, и вакансий на нем больше будет.
    Но в любом случае, после Rust и на TS начинаешь писать иначе, лучше.
    Ответ написан
    Комментировать
  • Как найти и заменить значение вложенного объекта?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function cloneWithReplace(
        // клонируемый объект
        obj,
        // объект с функциями вида value => newValue, в соответствующих ключах для замены
        // нужен не всегда, поэтому по умолчанию сделаем пустой объект
        replacers = {},
        // Map с значениями, которые уже склонировали, дабы не попасть в рекурсию
        // так как внешний код обычно его не будет передавать, зададим значение по умолчанию
        storeMap = new Map()
    ) {
        // для начала чекнем, что объект уже клонировали:
        if(storeMap.has(obj)) {
            return storeMap.get(obj);
        }
    
        // получим тип объекта, он нам пригодится пару раз, дабы отличать функции
        const type = typeof obj;
    
        // если obj примитив, то его можно просто вернуть
        if(obj === null || (type !== 'object' && type !== 'function')) {
            return obj;
        }
    
        // создадим переменную с результатом и инициируем ее в зависимости от типа оригинала
        let result;
        if(type === 'function') {
            // функцию можно "склонировать" лишь обернув
            result = function() {
                return obj.apply(this, arguments);
            };
            // неплохо бы, чтоб клон правильно сообщал имя функции и количество аргументов
            // но так как IE не ест такую магию, обернем в try-catch
            try {
                Object.defineProperties(result, {
                    name: Object.getOwnPropertyDescriptor(obj, 'name'),
                    length: Object.getOwnPropertyDescriptor(obj, 'length')
                });
            } catch {}
        } else if(Array.isArray(obj)) {
            // массивы клонируем рекурсивно, при помощи map
            result = obj.map(value => cloneWithReplace(value, replacers, storeMap));
            // так как нормальные массивы не содержат других полей, кроме числовых
            // можно сохранить клон в защиту от рекурсии и вернуть результат
            storeMap.set(obj, result);
            return result;
        } else {
            // для всех других объектов просто создадим новый объект и скопируем ему ссылку на прототип
            result = Object.setPrototypeOf({}, Object.getPrototypeOf(obj));
        }
    
        // сохраним клон в защиту от рекурсии
        storeMap.set(obj, result);
    
        // осталось склонировать поля с заменой тех случаев, где у нас есть replacer
        for(const key of Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))) {
            if(typeof replacers[key] === 'function') {
                // если есть replacer используем его
                result[key] = replacers[key](obj[key]);
            } else {
                // иначе клонируем поле рекурсивно
                result[key] = cloneWithReplace(obj[key], replacers, storeMap);
            }
        }
    
        return result;
    }
    
    // используем так:
    const newData = cloneWithReplace(data, {
        value: () => 'new value'
    });
    Ответ написан
    1 комментарий
  • Github: Один локальный репозиторий на два удаленных?

    bingo347
    @bingo347
    Crazy on performance...
    https://git-scm.com/book/ru/v2/Инструменты-Git-Под...
    сделать папку build подмодулем, у которого remote будет публичный репо
    Ответ написан
    Комментировать
  • Как изменить текст в буфере перед вставкой?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    document.addEventListener('paste', pasteText);
    function pasteText(e) {
      e.preventDefault();
      var txt = (e.originalEvent || e).clipboardData.getData('text/plain');
      e.target.value = txt;
    };
    Ответ написан
    1 комментарий
  • Есть программа для создания таблиц с программным кодом?

    bingo347
    @bingo347
    Crazy on performance...
    В экселе в ячейку можно вставить функции, в том числе написанные собственноручно на VBA
    В OpenOffice/LibreOffice Calc помимо VBA так же доступны Lua и JS
    В Google Sheets то же самое можно сделать на JS
    Ответ написан
  • Как работает get и set в computed?

    bingo347
    @bingo347
    Crazy on performance...
    Это не геттер и сеттер без имени, это методы с именами get и set.
    Ответ написан
    Комментировать
  • Выполнить функцию когда скролл на нужной позиции?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Дату в объекте нужно распарсить в объект Date
    Сами даты приводятся операторами сравнения к числу (unix timestamp в милисекундах) и вполне себе сравниваются:
    const date = new Date('02-10-2005'); // это лучше вынести за цикл, что бы не делать много раз одно и то же
    for (card of json.CardInfo) {
       if(new Date(card.Date) < date) {
        console.log('true');
      } else{
        console.log('false');
      }
    }

    P.S. вообще конструкций вида if(...) { true } else { false } лучше избегать
    for (card of json.CardInfo) {
        console.log(String(new Date(card.Date) < date));
    }
    этот пример отработает абсолютно аналогично предыдущему, но читать кода тут меньше
    Ответ написан
    7 комментариев
  • Стоит ли учить С/С++ если не планируешь писать на нём?

    bingo347
    @bingo347
    Crazy on performance...
    Языки не нужно учить. Это крайне вредно. Ну заучите Вы синтаксис и базовые принципы, а что дальше? Программировать с этим Вы не сможете. Подход выучить ЯП Х не работает, как и не работает подход выучить естественный. Просто подумайте, кто быстрее заговорит на английском - тот кто выучит много слов и правил или тот кто поедет в США и будет вынужден там общаться? С языками программирования все то же самое.

    Теперь о C и C++
    C наверно самый простой ЯП, проще только ассемблер. Из высокоуровневых абстракций в нем только типы данных да структурное программирование (if, for, while, ...). Вы скорее всего уже с этим всем знакомы. Из нового разве что будет работа с указателями, опять же максимально простым способом - в лоб.
    C++ - обвешали простой C максимальным количеством высокоуровневых абстракций (все виды полиморфизма, ООП, замыкания, динамическая диспетчеризация и т.д.), что сделало его очень сложным. Вам понадобятся годы практики (практики, а не зубрежки!), чтобы просто понять, что здесь происходит. А скорее всего Вы просто бросите это дело, породив пару десятков UB в простейшей программе и на ровном месте.
    Ответ написан
    Комментировать
  • Какой самый низкоуровневый язык програмирования?

    bingo347
    @bingo347
    Crazy on performance...
    Ассемблеры разные бывают, по сути для каждой архитектуры существует свой ассемблер. А еще для разных ОС могут быть диалекты. Ассемблер - это прямое соотношение машинных команд с более человекопонятным ассемблерными, нумерации регистров с их именами и т.д. Так что что-то посередине воткнуть не получится.

    P.S. когда уже русский язык станет самым популярным? Как Вы собираетесь с формальными языками разбираться, если не можете освоить естественный?
    Ответ написан
    1 комментарий
  • Как работает сборщик мусор с колбеками Promise?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Сборщики мусора (далее GC) бывают разные, в том же v8 используется сразу 3 типа GC в зависимости от поколения объектов (упрощенно молодое, старое и сложные случаи), но в большинстве своем принцип работы сводится к просчету достижимости из некоторого корня в дереве объектов (например глобального объекта, но не только его). v8 не является исключением, и его GC содержит C++ api для создания таких корней. Из JS мы данным api можем воспользоваться лишь косвенно, через сущности языка предоставляемые либо самим v8 либо платформой (браузером, node.js, deno и т.д.)
    Чтоб было понятно давайте рассмотрим простой пример:
    const h = 'Hello world!';
    const n = 'nothing';
    setTimeout(() => {
      console.log(h);
    }, 1000);
    У нас есть строковые переменные h и n. Переменная n нигде больше не используется и ее память очистится при ближайшей работе GC. А вот переменная h оказалась в замыкании созданном стрелочной функцией. И хотя в JS мы не можем достучаться до h имея ссылку на эту функцию, сама функция все таки имеет ссылку на h, а значит h не может быть уничтожена пока не будет уничтожена сама функция. В терминах GC ссылка на h будет серой, то есть сама ссылка на h недоступна из корня напрямую, но сейчас мы проверяем объекты, которые на нее ссылаются и истина будет зависеть от них (подробнее можете погуглить "mark black white and gray memory in gc").
    Давайте посмотрим на саму стрелочную функцию, которая держит h в замыкании. Из кода видно, что мы ее передаем в функцию setTimeout, о которой известно, что это api предоставленное платформой (а значит вероятно какая-то часть написана на C++), а так же, что она асинхронная. Платформе реализующей setTimeout наша функция понадобится после асинхронного ожидания и никто платформе не сможет гарантировать, что во время этого ожидания не будет работы GC, поэтому ей ничего не остается, кроме как запросить у v8 создание нового корневого дерева объектов, в которое и будет положена ссылка на данную функцию.
    После же выполнения таймаута платформе больше не нужна наша функция, поэтому ссылка на нее будет удалена из дерева объектов. А так как других ссылок на функцию нет, и она больше не доступна ни из одного корня - GC удалит из памяти и функцию и строку связанную h, которая так же стала недоступна из корня.

    Посмотрим на пример из вопроса. У нас есть стрелочная функция, которая удерживает на себе инстанс компонента через this ссылку (так как стрелочные функции замыкают this). Саму функцию в памяти удерживает промис порожденный вызовом loader('url'), так как мы отдали её в метод then. Других ссылок на данную функцию нет, а значит и сама функция и ее замыкание (инстанс компонента) будут "жить" не менее "жизни" промиса.
    Скажем был отправлен запрос на сервер, но потом компонент в котором был объявлен промис и колбек был удален.
    И после удаления приходит ответ от сервера, и он выполнит колбек. Это значит что колбек остался в памяти со всеми переменными контекста
    Если других ссылок не осталось, то инстанс компонента будет удерживаться от очистки через промис.

    Теперь стоит разобраться с самим промисом. У него может быть 3 состояния - pending, resolved или rejected. После перехода в состояния resolved или rejected промис может выполнить сохраненные колбэки в ближайшем микротаске, а после он удалит на них ссылки из себя, в следствии чего, память удерживаемая замыканием колбэка может быть очищена (при отсутствии на нее других ссылок, достижимых из какого-либо корня).
    В состоянии pending промис может потенциально находится бесконечно долго, при этом ссылаясь на все колбэки переданные ему в методы then, catch или finally, а значит так же косвенно ссылаясь на их замыкания. И тут все зависит от того, кто ссылается на данный промис, и достижим ли он из корня. И да, промис вполне может быть удален из памяти так и не дождавшись своего завершения.
    интересное умозаключение
    Если Promise - это обещание, то в данном случае оно будет нарушено?


    В комментах к вопросу есть еще один интересный пример:
    function getSomething(){
      return new Promise((resolve, reject)=>{
        if(sys_condition){
           resolve();
        } 
      })
    }
    
    function testPromise(){
      let config = {....}
      getSomething().then(()=>{
         #use config
         goOn(...config)
      })
    }
    
    testPromise();
    У нас есть вызванная 1 раз функция testPromise, которая получает из функции getSomething промис, в который с помощью метода then сохраняет колбэк, удерживающий в замыкании переменную config. Сам промис она нигде не сохраняет, что здесь очень важно.
    В функции getSomething мы просто возвращаем промис созданный через его конструктор, который как мы уже знаем нигде больше не сохраняется. И на этом могло бы все и закончится, без вызова колбэка независимо ни от чего. Но конструктор промиса выполняет свой колбэк синхронно, а кроме того он передает в него 2 функции - resolve и reject, которые в своем замыкании ссылаются на только что созданный промис (а это уже 2 ссылки на него, хотя мы то его никуда не сохраняли). Переменная reject никак не используется, а значит спокойно может быть удалена после завершения колбэка. Переменная resolve просто вызывается как функция внутри условия, но более тоже никак не используется и никуда не сохраняется, а значит так же может быть удалена.
    В этом примере. если sys_condition = false и resolve не вызовется, это значит что создается утечка памяти
    Нет, утечки памяти не будет. Колбэк созданный в testPromise будет удален вместе с замыканием, так и не вызвавшись ни разу.
    Ответ написан
    3 комментария
  • Как отсортировать объект по вложенному массиву?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const newArray = arr.slice(); // так как sort мутирует массив, а нужен новый
    const isAnnaSkill = skill => skill.name === 'Anna';
    const getAnnaLevel = item => item.skills.find(isAnnaSkill)?.level;
    newArray.sort((a, b) => getAnnaLevel(b) - getAnnaLevel(a));
    Ответ написан
    2 комментария
  • Как обработать 2 запроса одновременно в node.js?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Комментировать
  • Как прокачать навыки функционального программирования?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Я бы начал с изучения книги Луиса Атенсио "Функциональное программирование на ...
    Дальше можно изучить серию статей "Мышление в стиле Ramda" на хабре
    Ответ написан
    Комментировать
  • Как узнать какой global user.name и global user.email и как переключиться на старом акаунте гитхаба?

    bingo347
    @bingo347
    Crazy on performance...
    git config --global --get user.name
    git config --global --get user.email

    С аккаунтом github это никак не связано, все хранится локально у Вас на компе

    Глобальные конфиги лежат в файле $HOME/.gitconfig
    Локальные - в ближайшей папке .git вверх по дереву
    Ответ написан
    Комментировать
  • Что следует почитать/посмотреть для изучения Git?

    bingo347
    @bingo347
    Crazy on performance...
    Ответ написан
    Комментировать
  • Как посчитать количество повторений символов в строке?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    То что у Вас в полях created и viewed вполне можно отдать в конструктор Date, а даты уже можно сравнивать между собой
    console.log(new Date("2020-05-22 16:24:16")); // работает

    Дальше, последний created, тут нужно уточнение:
    Если массив messages всегда упорядочен по полю created, как и в примере, то можно просто брать последний элемент массива и работать с ним:
    const lastMessage = messages[messages.length - 1];
    console.log(lastMessage);

    Если такой гарантии нет, то нужно искать максимум:
    const lastMessage = messages.reduce(([maxDate, maxMessage], currentMassage) => {
      const currentDate = new Date(currentMassage.created);
      if(currentDate > maxDate) {
        return [currentDate, currentMassage];
      }
      return [maxDate, maxMessage];
    }, [-Infinity, null])[1];
    console.log(lastMessage);

    Ну а если с этим разберетесь, то с последним пунктом у Вас уже не должно быть проблем, тут все аналогично
    Ответ написан
    3 комментария