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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вашу хотелку можно сделать одним простым выражением:
    const consoleArray = Object.keys(console).filter(
      k => typeof console[k] === 'function'
    ).reduce(
      ([cnsl, acc], key) => [Object.assign(cnsl, {
        [key]: (original => (...args) => (
          acc.push(...args),
          original.call(cnsl, acc)
        ))(cnsl[key])
      }), acc],
      [console, []]
    )[1];
    Ответ написан
    1 комментарий
  • Почему XOR 0 убирает дробную часть числа?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Почему число получается целым, уже объяснил Stranger in the Q
    Я же постараюсь объяснить, как это работает, и почему оно не лучше Math.floor:
    В js тип number представлен числами двойной точности по стандарту кодирования IEEE 754, а это значит, что 53 бита выделяются под значимую часть (старший бит - бит знака, если 1 - то число отрицательное) и 11 бит под экспоненту (старший бит опять же бит знака), всего выходит 64 бита. Притом данный стандарт позволяет абсолютно точно работать с целыми числами до ±252 и поэтому до не давнего времени в js честного int не было.
    Теперь к бинарным (не нравится мне перевод "побитовый") операциям, как известно "исключающее или" (xor, ^) с нулем, а так же "или" (or, |) с нулем не меняют число, возвращая другой операнд в неизменном виде. Но тут вклинивается стандарт js и говорит, что бинарные операции выполняются над signed int32 представлением числа и при представлении можно просто отбросить все лишнее, что движки и делают.
    Как отбросить все лишние? Да просто, движок js прекрасно знает, в какой части числа расположена значимая часть, он просто берет младшие 32 бита значимой части и кладет их в int32 контейнер ну и еще переносит бит знака на свое место. Обратное преобразование похоже - в нулевой float64 контейнер раскладываем: старший бит (знак) на свое место, остальные 31 бит - на свое.

    А теперь давайте поэкспериментируем в обычной браузерной консоли:
    Math.floor(1.1) // 1
    parseInt(1.1) // 1
    1.1 | 0 // 1
    1.1 ^ 0 // 1 - как уже писал выше, эффект будет 1 в 1, как и с |
    
    // пока все было ок, но как насчет отрицательных чисел?
    Math.floor(-1.1) // -2 - округляем в сторону -Infinity
    parseInt(-1.1) // -1 - отбрасываем экспоненту
    -1.1 | 0 // -1 - отбрасываем экспоненту и не только (но тут не имеет значения пока)
    
    // попробуем с чем-нибудь побольше
    2 ** 31 // 2147483648
    2147483648 | 0 // -2147483648
    /*
    не зная как преобразовывается число выше, это было бы не очевидно
    но смотрим выше "он просто берет младшие 32 бита значимой части и кладет их в int32 контейнер"
    2 ** 31 в двоичном виде - это единичка и 31 нолик
    и эта единичка попала в бит знака при переноси в int32
    тем самым мы получили самое маленькое число в int32
    */
    
    // давайте еще пример, набью как я большое число от балды:
    34646456436346346212424 // 3.464645643634635e+22
    34646456436346346212424 | 0 // 1178599424
    /*
    ну в первом примере мы видим интересную особенность чисел с плавающей запятой
    мы можем хранить не только дробные числа, но и очень большие целые, правда с потерей точности
    e+22 - это и есть экспонента, это значит число до e нужно умножить на основание системы счисления (10) в степени +22
    а при бинарной операции эта экспонента отбрасывается, как и старшие биты значимой части
    в 32 младших битах осталось 1178599424
    забавно, что я случайно вбил такое число, у которого 32 бит содержал 0 (шансы были 50/50)
    если бы там оказалась 1, то я бы вновь получил отрицательное число
    */
    Ответ написан
    Комментировать
  • Сравнение строк JS?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Импорт модуля ради «побочных эффектов»?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Для начала стоит понять сам термин "побочный эффект".
    Вот Вы вызываете функцию, а она что-то делает за своими пределами, например пишет в файл или localStorage, или меняет Ваш DOM на странице, или меняет глобальные объекты. Это и есть побочные эффекты.
    Модуль тоже может иметь побочные эффекты. Например Вы можете не просто экспортировать некоторые функции из модуля, но и сразу что-то сделать, вне всяких функций.
    Например пусть у нас будет такой модуль:
    const div = document.body.appendChild(document.createElement('div'));
    
    export function remove() {
      document.body.removeChild(div);
    }
    Даже если мы просто импортируем его, но не вызываем функцию remove, он все равно произведет свой побочный эффект - добавит новый div в body. И это произойдет при первом встретившемся импорте.
    Нам в принципе может быть и не нужна функция remove (ее даже может и не быть), но нам нужен этот div в body - тогда можем просто сделать импорт как в Вашем примере и получить div в body в качестве результата.

    Конкретно в контексте вебпака и импортирования стилей, у Вас скорее всего будет включен в обработку или style-loader или MiniExtractCssPlugin.loader. Побочный эффект style-loader - добавление тега style со стилями из импортируемого css в head. А у MiniExtractCssPlugin.loader - побочный эффект - извлечение стилей в отдельный файл.
    Ответ написан
    1 комментарий
  • Redux для "не React проектов"?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Правильным ли решением будет использовать redux для обычного веб-ресурса
    Почему бы и нет. Redux не имеет никакого отношения к React от слова совсем.

    Или есть альтернативы ?
    Ну можете взять обычный compose из lodash/ramda (в ramda кстати есть линзы, которые хорошо помогают работать с иммутабельными объектами) и соединить им Ваши "редьюсеры". Положить объект в переменную state в замыкании, и все - свой redux готов.
    Можно так же глянуть в сторону mobx или svelte/store если действительно хочется реактивности, а не тупого клонирования объектов
    Ответ написан
    Комментировать
  • Как скрыть ссылку от индексации посредством скрипта?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    скрыть ссылку от индексации посредством скрипта
    От поисковых роботов? Им вполне может быть пофик, как там скрипты DOM меняют, они вполне могут проиндексировать страницу как до выполнения скриптов, так и после.
    Если нужно запретить индексировать определенные страницы - для этого есть robots.txt - погуглите, уверен, что этот то что нужно.
    А еще советую подумать, а можно ли будет по Вашим импровизированным ссылкам ходить скринридером? А просто табом?
    Яндекс к сожалению еще до этого не допер, но вот гугл вполне может снизить Ваш сайт в выдаче за ухудшение a11y
    Ответ написан
    Комментировать
  • Как красиво записать присвоение на js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    ((req.query || (req.query = {})).where || (req.query.where = {})).profile = 1;

    или
    const {query = (req.query = {})} = req;
    const {where = (query.where = {})} = query;
    where.profile = 1;
    Ответ написан
    Комментировать
  • Как организовать асинхронную функцию .map?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    let rawNews = []; // Массив объектов (Свеженькие новости прямо из БД)
    let rawCats = []; // Массив объектов с обработанными новостями
    // Промис с массивом результатов
    let modifyNews = Promise.all(rawNews.map(async (item, i, arr) => {
        item.autor = await getUserByID(item.autor); // Асинхронная функция которая выставляет имя автора вместо id
        return item;
    }));
    Ответ написан
    1 комментарий
  • Как сделать диагональный scroll?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Я бы так сделал:
    // export или module.export =
    function formatText(text, formatters) {
      return formatters.reduceRight(applyFormatter, text);
    }
    
    function applyFormatter(text, formatter) {
      const {offset, length, type} = formatter;
      const endOffset = offset + length;
      const wrapper = getWrapper(type);
      return `${text.slice(0, offset)}${wrapper(
        text.slice(offset, endOffset),
        formatter
      )}${text.slice(endOffset)}`;
    }
    
    function getWrapper(type) {
      switch(type) {
      case 'bold':
        return boldWrapper;
      case 'text_link':
        return linkWrapper;
      default:
        return identityWraper;
      }
    }
    
    function boldWrapper(text) {
      return `<b>${text}</b>`;
    }
    function linkWrapper(text, {url}) {
      return `<a href="${url}">${text}</a>`
    }
    function identityWraper(text) {
      return text;
    }

    Использование:
    console.log(formatText('qwerty Ссылка', [
      { offset: 0, length: 7, type: 'bold' },
      { offset: 7, length: 6, type: 'text_link', url: 'https://vk.com/' }
    ])); // <b>qwerty </b><a href="https://vk.com/">Ссылка</a>
    Ответ написан
    Комментировать
  • Как работает оператор +?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В js оператор + перегружен. Можно представить, что под капотом он вызывает функцию от двух аргументов (левого и правого операнда), примерно такую:
    function add(left, right) {
      const typeLeft = typeof left;
      const typeRight = typeof right;
      if(typeLeft === 'string') {
        return left.concat(right);
      }
      if(typeRight === 'string') {
        return right.concat(left);
      }
      if(canConvertToNumber(left, typeLeft) && canConvertToNumber(right, typeRight)) {
        return Number(left) + Number(right); // тут уже не перегруженный вариант + иначе будет бесконечная рекурсия
      }
      if(typeLeft === 'bigint' && typeRight === 'bigint') {
        return left + right; // опять не перегруженный вариант
      }
      if(
        (typeLeft === 'bigint' && canConvertToNumber(right, typeRight))
        || (typeRight === 'bigint' && canConvertToNumber(left, typeLeft))
      ) {
        // если предыдущий if не прошел, а проходит этот
        // то мы складываем bigint с не bigint, а так нельзя
        throw new TypeError('Cannot mix BigInt and other types, use explicit conversions');
      }
      // во всех остальных случаях приводим к строке:
      return String(left).concat(right);
    }
    
    function canConvertToNumber(item, type) {
      return item === null || type === 'number' || type === 'boolean' || type === 'undefined';
    }
    Ответ написан
    Комментировать
  • Как организовать более правильно скрипты на сайте?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    делаю проект на laravel
    Значит у Вас уже есть laravel-mix, который под капотом использует webpack, а значит можно нормально работать с import

    А потом эти классы импортировать и объекты уже этих классов делать глобальными:
    window.text= new Text();
    window.cart = new Cart();
    window.Form = new Form();

    Что бы потом это не получилось в неуправляемую кашу.
    Как раз такой подход приведет к неуправляемой каше.
    А потом уже в разметке в событиях вызывать методы соответствующих объектов
    Да Вы батенька мазахист...
    Ответ написан
  • Как сделать объект доступным во всех файлах без импорта?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Можно положить в global, хотя это и не очень хорошая практика
    Ответ написан
  • Почему я могу изменять массив при использовании const?

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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если стили на нашей странице, то через CSSOM (хорошо гуглится)
    Так же можете поисследовать в консольке document.styleSheets
    Ну и нужно учитывать, что для кроссдоменных стилей нужен CORS
    Ответ написан
  • Зачем передавать самовызываемой функции параметр undefined?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Помимо защиты от подмены, уже описанной в других случаях, аргумент функции будет сокращен до 1 буквы при манглинге кода, что по сравнению с использованием глобального значения позволяет экономить 8 байт бандла на каждое использование undefined
    Аналогично часто делают с window и document
    Ответ написан
  • Итерируемые объекты, почему в цикле первое значение 1?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В JS есть по 2 оператора инкримента и декримента
    Так
    let x = 10;
    console.log(x++); // 10
    console.log(x--); // 11
    значение сначала будет передано в console.log, а потом посчитано новое
    А так
    let x = 10;
    console.log(++x); // 11
    console.log(--x); // 10
    сначала посчитает, а потом передаст в console.log
    С присваиванием и назначением ключу объекта происходит тоже самое
    Ответ написан
    Комментировать
  • Что входит в JavaScript Basic?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Учить можно стихи. Языки, особенно программирования, учить бесполезно.

    Нужно брать, и что-то делать, что-то реальное. Владение языком, неважно английским или JavaScript, приходит только с практикой.
    Так же не плохо освоить (не выучить, а именно освоить, овладеть) программированием в целом, а так же основами Computer Science, дискретной математики, мат. логики и других смежных дисциплин.
    Ответ написан
    Комментировать
  • Как сократить такой код, Waypoints.js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    var allWaypoints = [];
    $('.any, .odds, .simple, .faq, .doctors, .consultation, .stages, .start, .seven').each(function() {
      var $this = $(this);
      allWaypoints.push($this.waypoint(function(direction) {
        $this.addClass('loader');
      }));
    });
    Ответ написан
    1 комментарий