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

    Seasle
    @Seasle Куратор тега JavaScript
    const inputOutput = document.getElementById('usd');

    В обработчике изменяете код:
    const value = (input.value * 73.84).toFixed(5) + ' $';
    inputResult.value = value;
    inputOutput.textContent = value;
    Ответ написан
    1 комментарий
  • Как получить максимальное число из массива?

    Seasle
    @Seasle Куратор тега JavaScript
    const numbers = [-78, -20, -10];
    console.log(Math.max(...numbers)); // -10
    Ответ написан
    Комментировать
  • Как написать условие с проверкой элемента на JS?

    Seasle
    @Seasle Куратор тега JavaScript
    const resultContainer = document.querySelector('.result');
    if (resultContainer.classList.contains('win')) {
        // ...
    } else if (resultContainer.classList.contains('lose')) {
        // ...
    }
    Ответ написан
    1 комментарий
  • Как поставить курсор на input при переходе к форм?

    Seasle
    @Seasle Куратор тега CSS
    Ответ написан
    Комментировать
  • Объясните пожалуйста как понять такое поведение promise?

    Seasle
    @Seasle Куратор тега JavaScript
    Вывод в консоль не в том порядке, который идёт по коду сверху вниз вызван тем, что в обещаниях мы можем выполнять некоторые долгие операции (например, запросы в бэкенд). В тот момент, когда происходит привязка then, catch и finally интерпретатор не будет ждать их выполнения и пойдет дальше. В итоге после "обхода" кода есть два "места", в которые вернется результат обещания. В первом promise, во время выполнения then мы не знаем, сколько времени потребуется для его выполнения, поэтому интерпретатор идет дальше, к следующему обещанию (в данном случае - "привязке"). Если хотите сделать так, чтобы обещания выполнялись именно в том порядке, который описан в коде, то надо писать как-то так:
    (async () => {
      const promise = new Promise((resolve, reject) => {
        resolve(console.log('start'));
      });
    
      await promise
        .then(x => console.log('x'))
        .then(y => console.log('y'));
    
      await promise.then(z => console.log('z'));
    })();

    или так:
    const start = async () => {
      const promise = new Promise((resolve, reject) => {
        resolve(console.log('start'));
      });
    
      await promise
        .then(x => console.log('x'))
        .then(y => console.log('y'));
    
      await promise.then(z => console.log('z'));
    };
    
    start();

    или так (если в Вашей среде работает top level await):
    const promise = new Promise((resolve, reject) => {
      resolve(console.log('start'));
    });
    
    await promise
      .then(x => console.log('x'))
      .then(y => console.log('y'));
    
    await promise.then(z => console.log('z'));
    Ответ написан
  • Почему JS самостоятельно изменяет числа?

    Seasle
    @Seasle Куратор тега JavaScript
    console.log(Number.MAX_SAFE_INTEGER < 9999999999999999); // true

    Используйте BigInt
    console.log(9999999999999999n); // 9999999999999999n
    Ответ написан
    1 комментарий
  • Как получить первые буквы в строке до цифр?

    Seasle
    @Seasle Куратор тега JavaScript
    const getCharsUntilNumbers = string => string.match(/^([a-z]+)/i)?.[0];
    
    console.log(getCharsUntilNumbers('dev05_dddd')); // 'dev'
    console.log(getCharsUntilNumbers('01')); // undefined
    console.log(getCharsUntilNumbers('de06')); // 'de'
    Ответ написан
    4 комментария
  • Почему не работает forEach?

    Seasle
    @Seasle Куратор тега JavaScript
    Если хотите их сохранить в новом массиве, тогда так:
    - a9.forEach(function(elem) {
    -   elem.toLowerCase();
    - });
    - 
    - return a9;
    + return a9.map(function (elem) {
    +   return elem.toLowerCase();
    + });

    Если хотите сохранить в существующий массив, тогда так (правда смысла в этом не много):
    - a9.forEach(function(elem) {
    -   elem.toLowerCase();
    - });
    + a9.forEach(function(elem, i, arr) {
    +   arr[i] = elem.toLowerCase();
    + });

    или
    - a9.forEach(function(elem) {
    -   elem.toLowerCase();
    - });
    + for (let index = 0; index < a9.length; index++) {
    +   a9[index] = a9[index].toLowerCase();
    + }
    Ответ написан
    4 комментария
  • Расставить ромбики в нужных координатах, ориентируясь на виртуальные координаты?

    Seasle
    @Seasle Куратор тега JavaScript
    Это называется изометрия. Можете посмотреть эти видео:
    Ответ написан
    Комментировать
  • Как сделать так, чтобы одновременно могло работать не более одного экземпляра функции?

    Seasle
    @Seasle Куратор тега JavaScript
    Речь о чём-то похожем?
    const singleBusinessLogic = (() => {
      let isBusy = false;
      let promise = null;
      let done = null;
      let failure = null;
      
      return (id) => {
        if (!isBusy) {
          isBusy = true;
          promise = new Promise((resolve, reject) => ([done, failure] = [resolve, reject]));
          
          fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
            .then(response => response.json())
            .then(done)
            .catch(failure)
            .finally(() => (isBusy = false));
        }
        
        return promise;
      };
    })();
    
    (async () => {
      console.log(await singleBusinessLogic(1)); // { ..., name: 'Leanne Graham', ... }
      console.log(await singleBusinessLogic(2)); // { ..., name: 'Leanne Graham', ... }
      setTimeout(async () => {
        console.log(await singleBusinessLogic(3)); // { ..., name: 'Clementine Bauch', ... }
        console.log(await singleBusinessLogic(4)); // { ..., name: 'Clementine Bauch', ... }
      });
    })();

    Или хотите возвращать результат только самого первого вызова?
    Ответ написан
    4 комментария
  • Почему не срабатывает clearTimeout?

    Seasle
    @Seasle Куратор тега JavaScript
    printNumbers(1, 5);
    
    function printNumbers(from, to) {
      let current = from;
      let timerId = setTimeout(function go() {
        timerId = setTimeout(go, 1000);
    
        console.log(`current: ${current}`);
        
        if (current === to) {
          clearTimeout(timerId);
        }
        
        current++;
      }, 1000);
    }
    Ответ написан
    2 комментария
  • Как заставить функцию ждать пока другая не вернёт результат?

    Seasle
    @Seasle Куратор тега JavaScript
    Пример 1 - fetch, async/await
    async function start() {
      const user = await getUser();
      
      console.log(user);
    }
    
    function getUser() {
      return fetch('https://jsonplaceholder.typicode.com/users/1')
        .then(response => response.json());
    }
    
    start();
    /*
    {
      id: 1,
      name: 'Leanne Graham',
      username: 'Bret',
      email: 'Sincere@april.biz',
      address: {
        street: 'Kulas Light',
        suite: 'Apt. 556',
        city: 'Gwenborough',
        zipcode: '92998-3874',
        geo: { lat: '-37.3159', lng: '81.1496' }
      },
      phone: '1-770-736-8031 x56442',
      website: 'hildegard.org',
      company: {
        name: 'Romaguera-Crona',
        catchPhrase: 'Multi-layered client-server neural-net',
        bs: 'harness real-time e-markets'
      }
    }
    */

    или
    Пример 2 - XHR, async/await
    async function start() {
      const user = await getUser();
      
      console.log(user);
    }
    
    function getUser() {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        
        xhr.open('GET', 'https://jsonplaceholder.typicode.com/users/1');
        xhr.addEventListener('load', () => {
          if (xhr.status === 200) {
            resolve(JSON.parse(xhr.response));
          } else {
            reject(xhr.response);
          }
        });
        
        xhr.send();
      });
    }

    или
    Пример 3 - XHR, callback
    function start() {
      getUser(user => {
        console.log(user);
      });
    }
    
    function getUser(callback) {
      const xhr = new XMLHttpRequest();
    
      xhr.open('GET', 'https://jsonplaceholder.typicode.com/users/1');
      xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
          callback(JSON.parse(xhr.response));
        } else {
          callback(xhr.response);
        }
      });
    
      xhr.send();
    }
    
    start();

    Для варианта с функцией обратного вызова, чаще всего используют два параметра: первый - ошибку, второй - результат, тогда код будет выглядеть так:
    Пример 4 - XHR, callback с обработкой ошибок
    function start() {
      getUser((error, user) => {
        if (!error) {
          console.log(user);
        }
      });
    }
    
    function getUser(callback) {
      const xhr = new XMLHttpRequest();
    
      xhr.open('GET', 'https://jsonplaceholder.typicode.com/users/1');
      xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
          callback(null, JSON.parse(xhr.response));
        } else {
          callback(new Error(xhr.response));
        }
      });
    
      xhr.send();
    }
    
    start();

    Также, для XHR надо дополнительно обрабатывать ошибки.
    Ответ написан
    Комментировать
  • Как игнорировать \n в строке?

    Seasle
    @Seasle Куратор тега JavaScript
    Экранируйте тогда его.
    Ответ написан
    Комментировать
  • Почему alert([] + true + false - null ) и alert(true + false - null + [] ) ведут себя по разному?

    Seasle
    @Seasle Куратор тега JavaScript
    Потому что на самом деле так:
    [].toString() + true + false - null
    "" + true // "true"
    "" + true + false // "truefalse"
    "" + true + false - null // NaN

    Если один из операндов + не строка, то это не конкатенация и true, false, null будут преобразованы к числам.
    true + false - null + [].toString()
    1 + 0 // 1
    1 + 0 - 0 // 1
    1 + 0 - 0 + "" // "1"
    Ответ написан
    Комментировать
  • Почему tampermonkey скрипт не может использовать setInterval?

    Seasle
    @Seasle Куратор тега JavaScript
    Для начала либо так:
    document.getElementsByClassName('hypertrain-avatar')[0].getAttribute('style')

    либо так:
    document.querySelector('.hypertrain-avatar').getAttribute('style')
    Ответ написан
    Комментировать
  • Как правильно реализовать (Level System) для игры?

    Seasle
    @Seasle Куратор тега JavaScript
    Возможно как-то так:
    Пример 1
    const lerp = (min, max, value) => (1 - value) * min + value * max;
    
    const LEVELS = 10;
    const MAX_EXPERIENCE = 600000;
    
    const multipliers = [];
    for (let index = 0; index < LEVELS - 1; index++) {
      multipliers.push(
        lerp(1, 2, index / LEVELS)
      );
    }
    
    const total = multipliers.reduce((total, value) => total + value, 0);
    const step = MAX_EXPERIENCE / total;
    const { levels } = multipliers.reduce((store, multiplier, index) => {
      const experience = step * multiplier;
      store.levels.push({
        level: index + 1,
        experience: {
          current: store.total,
          next: store.total + experience,
          need: experience
        }
      });
      store.total += experience;
      
      if (index + 1 === LEVELS - 1) {
        store.levels.push({
          level: LEVELS,
          experience: {
            current: store.total
          }
        });
      }
      
      return store;
    }, { levels: [], total: 0 });
    
    console.log(levels);
    /*
    [
      {
        level: 1,
        experience: { current: 0, next: 47619.04761904762, need: 47619.04761904762 }
      },
      {
        level: 2,
        experience: { current: 47619.04761904762, next: 100000, need: 52380.95238095238 }
      },
      {
        level: 3,
        experience: { current: 100000, next: 157142.85714285716, need: 57142.85714285715 }
      },
      {
        level: 4,
        experience: { current: 157142.85714285716, next: 219047.61904761905, need: 61904.761904761894 }
      },
      {
        level: 5,
        experience: { current: 219047.61904761905, next: 285714.2857142857, need: 66666.66666666666 }
      },
      {
        level: 6,
        experience: { current: 285714.2857142857, next: 357142.8571428571, need: 71428.57142857142 }
      },
      {
        level: 7,
        experience: { current: 357142.8571428571, next: 433333.3333333333, need: 76190.4761904762 }
      },
      {
        level: 8,
        experience: { current: 433333.3333333333, next: 514285.71428571426, need: 80952.38095238095 }
      },
      {
        level: 9,
        experience: { current: 514285.71428571426, next: 600000, need: 85714.28571428571 }
      },
      {
        level: 10,
        experience: { current: 600000 }
      }
    ]
    */

    В примере выше используется линейная интерполяция. На её основе можете изменить шаг между уровнями, например, используя easeInCubic в нормализованном значении:
    Пример 2
    const lerp = (min, max, value) => (1 - value) * min + value * max;
    const easeInCubic = value => value * value * value;
    
    const LEVELS = 10;
    const MAX_EXPERIENCE = 600000;
    
    const multipliers = [];
    for (let index = 0; index < LEVELS - 1; index++) {
      multipliers.push(
        lerp(1, 2, easeInCubic(index / LEVELS))
      );
    }
    
    const total = multipliers.reduce((total, value) => total + value, 0);
    const step = MAX_EXPERIENCE / total;
    const { levels } = multipliers.reduce((store, multiplier, index) => {
      const experience = step * multiplier;
      store.levels.push({
        level: index + 1,
        experience: {
          current: store.total,
          next: store.total + experience,
          need: experience
        }
      });
      store.total += experience;
      
      if (index + 1 === LEVELS - 1) {
        store.levels.push({
          level: LEVELS,
          experience: {
            current: store.total
          }
        });
      }
      
      return store;
    }, { levels: [], total: 0 });
    
    console.log(levels);
    /*
    [
      {
        level: 1,
        experience: { current: 0, next: 58275.058275058276, need: 58275.058275058276 }
      },
      {
        level: 2,
        experience: { current: 58275.058275058276, next: 116608.3916083916, need: 58333.33333333333 }
      },
      {
        level: 3,
        experience: { current: 116608.3916083916, next: 175349.65034965036, need: 58741.258741258745 }
      },
      {
        level: 4,
        experience: { current: 175349.65034965036, next: 235198.13519813522, need: 59848.48484848485 }
      },
      {
        level: 5,
        experience: { current: 235198.13519813522, next: 297202.79720279726, need: 62004.66200466201 }
      },
      {
        level: 6,
        experience: { current: 297202.79720279726, next: 362762.2377622378, need: 65559.44055944055 }
      },
      {
        level: 7,
        experience: { current: 362762.2377622378, next: 433624.70862470864, need: 70862.47086247086 }
      },
      {
        level: 8,
        experience: { current: 433624.70862470864, next: 511888.1118881119, need: 78263.40326340326 }
      },
      {
        level: 9,
        experience: { current: 511888.1118881119, next: 600000, need: 88111.88811188811 }
      },
      {
        level: 10,
        experience: { current: 600000 }
      }
    ]
    */
    Ответ написан
    Комментировать
  • Как сбросить цвет?

    Seasle
    @Seasle Куратор тега JavaScript
    const button = document.querySelector('.reset');
    button.addEventListener('click', () => {
        document.querySelectorAll('.active').forEach(element => element.classList.remove('active'));
    });

    ну и <div class="reset">сброс цвета</div> заменить на
    <button type="button" class="reset">сброс цвета</button>
    Ответ написан
    5 комментариев
  • Как через new Date() получить день недели и число?

    Seasle
    @Seasle Куратор тега JavaScript
    const format = (date) => {
      const formatted = date.toLocaleString('ru-RU', {
        weekday: 'long',
        day: 'numeric',
        month: 'long',
      });
      
      return `${formatted[0].toUpperCase()}${formatted.slice(1)}`;
    };
    
    const today = Date.now();
    const day = 24 * 60 * 60 * 1000;
    const tomorrow = format(new Date(today + day));
    const dayAfterTomorrow = format(new Date(today + day * 2));
    
    console.log(tomorrow); // 'Вторник, 6 июля'
    console.log(dayAfterTomorrow); // 'Среда, 7 июля'

    или
    const formatter = new Intl.DateTimeFormat('ru-RU', {
        weekday: 'long',
        day: 'numeric',
        month: 'long',
    });
    
    const format = (date) => {
      const formatted = formatter.format(date);
      
      return `${formatted[0].toUpperCase()}${formatted.slice(1)}`;
    };
    
    const today = Date.now();
    const day = 24 * 60 * 60 * 1000;
    const tomorrow = format(new Date(today + day));
    const dayAfterTomorrow = format(new Date(today + day * 2));
    
    console.log(tomorrow); // 'Вторник, 6 июля'
    console.log(dayAfterTomorrow); // 'Среда, 7 июля'
    Ответ написан
    Комментировать