Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как работает функция случайного числа от min до max?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Math.random() возвращает псевдослучайное с равномерной вероятостью в диапазоне от 0 до 1. Включая 0, исключая 1. Такой интервал ещё можно записать как [0, 1) — квадратная скобка означает включение числа, круглая – «дырку», исключение.

    Math.round() округляет дробные до «ближайшего» целого. От x - 0.5 (включая) до x + 0.5 (исключая) округлит до целого x. Можно записать так: [x-0.5, x+0.5)

    Функция получения случайного целого в диапазоне от min до max в описанном варианте старается сгладить вероятности всех целых до равных.

    Визуально это представить так: насыпается «дорожка» поваренной соли на диапазон от 0 до 1 – это равномерно распределённые вероятности из Math.random(). При этом сама "1" не участвует, но в данном случае это маловажно. Далее умножаем да диапазон, напр. на 4, и с помощью Math.round() делим отрезки этой дорожки в кучки для каждого целого. Кучки по краям получатся меньше остальных.

    Если случайное [0, 1) просто умножить на 4 и округлить Math.round() – будет выдавать случайные целые [0, 4] (а не до 3). И как неравновероятно!
    0                   1
    [...................)
    
    0    1    2    3    4
    00011111222223333344o


    Из-за того, что Math.round() разбивает пополам расстояние между двумя целыми, получится не 4 а 5 кучек. При чём в крайние, 0 и 4, попадёт всего по пол-интервала. Их вероятность будет 1/2 от полноценных вероятностей для 1, 2 и 3.

    Поэтому, в данной реализации генерируют от min-0.5 до max+0.5, чтобы после Math.round() вероятности всех целых были одинаковы.

    P. S. за эту размазанность Math.round() можно недолюбливать и вместо него округлять вниз, Math.floor() – так случайное целое, как в вашем вопросе, можно получить проще
    const rand = (min, max) => min + Math.floor(Math.random() * (max - min + 1));
    alert( rand(1, 3) );

    Кстати, в программировании часто предпочитают иметь дело с интервалами [ .. ) – включающими начало, но исключающими конец. Например, randomInteger(min, max) никогда бы не вернула max. А это задание вышло такое себе, нетрадиционное, у них )
    Ответ написан
    1 комментарий
  • Что значит " _ " в следующей arrow function: _ => store.shift()?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так записывают неиспользуемую переменную.

    Когда в функции не требуется аргумент, экономят 1 символ, чтобы не писать, как положено:
    () => somecode;

    Линтер такой юмор не оценит и будет ругаться.
    Ответ написан
    1 комментарий
  • Авторизация через VK на клиенте?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Два разных варианта авторизации пользователя в ВК:
    • Implicit flow. Для работы с API от имени пользователя в Javascript-приложениях и Standalone-клиентах (десктопных или мобильных).
    • Authorization code flow. Для работы с API от имени пользователя с серверной стороны Вашего сайта.


    Сейчас у вас реализован 2-й. А хотите 1-й.
    Ответ написан
    Комментировать
  • Можно ли на js сделать такой таймер?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Получите число миллисекунд от текущего момента до времени «Ч»:
    const che = new Date(2020, 0, 1);
    const now = new Date();
    let diff = Math.floor((che - now) / 1000); // в секундах


    Теперь от общего к частному. Дни - часы - минуты - секунды.
    Сначала число дней. В сутках 24 * 60 * 60 = 86400 секунд.
    const days = Math.floor(diff / 86400);
    // вычесть учтённые дни из остатка времени
    diff -= days * 86400;


    Далее так же с часами, минутами, остаток – секунды.

    И, высший пилотаж, изменять подпись в заисимости от числа:
    0 – дней – часов
    1 – день – час
    2 – дня  – часа

    Например, такой функцией:
    function declOfNum(number, titles) {  
        cases = [2, 0, 1, 1, 1, 2];  
        return titles[ (number%100>4 && number%100<20)? 2 : cases[(number%10<5)?number%10:5] ];  
    }
    
    // применение:
    declOfNum(days, ['день', 'дня', 'дней']); // массив из вариантов для 1, 2, 5
    Ответ написан
    Комментировать
  • Как сделать замену четных чисел на 0?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    function func_9() {
      let k = +prompt('Введите первое число');
      let i = +prompt('Введите второе число');
      if (k > i) {
        while (k > i) {
          if (k % 2 == 0) {  // это значит, что k четное - выведите 0
            k--;
            
          } else { // сюда попадаем если k нечетное, надо его просто вывести
            k += + k;  // тут ошибка: зачем-то k удваивается: к нему прибавляется оно же. Эта строка не нужна
            console.log(k); // ок
          }
          k--;
          console.log(k); // не надо
        }
      }
      else {
    // предупредите, что первое число вы ожидаете бОльшим, чем второе. Хотя логичнее просить вводитб первое число меньше, чем второе
        alert('arror');
      }
    }
    
    func_9();


    spoiler
    function funk_it_up() {
      const a = +prompt('Введите первое число');
      const b = +prompt('Введите второе число');
      if (a >= b) {
        alert('Первое число должно быть меньше второго');
        return;
      }
       
      for (let i = a + 1; i < b; i++) {
        console.log( i & 1 ? i : 0);
      }
    }
    
    funk_it_up();
    Ответ написан
    2 комментария
  • Как работает Array.prototype.slice.call?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Это один из способов преобразовать массиво-подобные HTMLCollection или Nodelist в настоящий массив со всеми его методами для последующей работы.

    Другой вариант сделать то же самое, с современным синтаксисом:
    const index = [...this.children];
    Ответ написан
    1 комментарий
  • Как считать RPS, если соединение устанавливается от 0 до 5 секунд?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Запросы имеют протяжённость во времени.
    Начало запроса — отправка запроса клиентом.
    Окончание – завершение получения данных клиентом и закрытие соединения.

    Неизвестно тут, что сервер считает за отметку времени запроса: его начало, конец, или что-то ещё.

    Допустим, разрешены 3 запроса в 1 секунду.
    Отправил 3 одновременно. Но 2 из них призадумались и тянутся по 5 секунд каждый, а один отыграл за 500 миллисекунд. Когда можно отправить ближайший следующий запрос?
    |--------------------|
    |--------------------|
    |--|
    0-----1-----2-----3--

    Гарантированно можно через 1 секунду после завершения 3-го быстрого, т.е. через 1500мс со «старта».

    И можно эвристически порисковать и чуть уменьшить эту паузу с окончания очередного запроса.

    Можно держать N «дорожек» – по числу одновременных запросов в единицу времени. И ставить очередной запрос на первую освободившуюся «дорожку».
    Ответ написан
    Комментировать
  • Как объединить несколько функций JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Исходный код можно примерно так отрефакторить. Вынести в аргументы то, что меняется:
    function addBehavior(idFrom, idTo, isChangingHeight) {
      const elFrom = document.getElementById(idFrom);
      const elTo = document.getElementById(idTo);
      
      const onOut = () => {
        elTo.style.width = "";
        isChangingHeight  &&  elTo.style.height = "";
    //    elFrom.removeEventListener(onOut);
      }
      
      const onOver = () => {
        elTo.style.width = "50%";
        isChangingHeight  &&  elTo.style.height = "50%";
    //     elFrom.removeEventListener(onOver);
      }
      
      elFrom.addEventListener("mouseover", onOver);  
      elFrom.addEventListener("mouseout", onOut);
    }
    
    addBehavior('gg', 'bg', true);
    addBehavior('zz', 'qq');

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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    id обязательно должны быть уникальными. Нельзя использовать один id для нескольких элементов.

    Зато className может присутствовать у многих элементов. Назначьте всем слайдам класс slide-item

    Upd. примерно так можно, коротко и просто:
    Ответ написан
  • Как управлять запросами к API на клиенте?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Писать свой или искать готовый механизм очереди с контролем времени.

    В очередь (массив) класть запрос (метод, параметры) и callback. Либо промисы.

    Держать массив с временем ответов последних 100 (30) вызовов. Если самый древний более 10 (5) секунд назад, можно выполнить очередной.

    Как-то написал вот такую
    кривую реализацию


    Модуль очереди:
    /**
     * Hold Your Horses!
     * Promise-based dispatcher that respects frequency limits.
     * It queues requests so that no more than N are processed within 1 second.
     * Those can go in parallel.
     *
     * Instantiate the new HH with options, specifying time limit.
     * Method .add(function) adds a new job to the queue.
     * Argument function should return Promise object that starts to process only after the function is called.
     * @return Object Promise.
     */
    
    function HorsesHolder(options) {
      options         = options || {};
      this.rps        = options.rps || 3; // requests per second
      this.parallel   = options.parallel || this.rps; // max parallel running jobs
    
      this.times      = []; // -1: slot is busy, 0: slot is free, positive timestamp - time slot's job has finished
      for (let i=0; i<this.rps; i++) this.times.push(0); // [0, 0, 0] initially
    
      this.queue      = [];
      this.inprogress = [];
      this.debug      = !!options.debug;
      
      this.debug  &&  console.log("%s ms: [HH] initialized", this.ts());
    }
    
    
    HorsesHolder.prototype.add = function(promiseMaker) {
      var self = this;
      
      return new Promise(function(resolve, reject) {
        self.queue.push({
          resolve: resolve,
          reject: reject,
          promiseMaker: promiseMaker,
        });
        
        self._ping();
      });
    };
    
    
    // Decide: work or wait
    HorsesHolder.prototype._ping = function() {
    
      if (this.queue.length === 0) {
        this.debug  &&  console.log("%s ms: [ping] queue is empty", this.ts());
        return;
      }
      
      const best = this._bestTime();
      
      if (best === -1) {
        this.debug  &&  console.log("%s ms: [ping] cannot go: %s", this.ts(), JSON.stringify(this.times));
        return;
      }
      
      const index = this.times.indexOf(best);
      
      this.debug  &&  console.info("%s ms: [ping] exec now at index %d", this.ts(), index);
    
      this._execute(index);
    }
    
    
    /**
     * Out of current times[] finds the best to occupy, if possible;
     * otherwise -1
     */
    HorsesHolder.prototype._bestTime = function() {
      let best = -1;
    
      for (let i=0; i<this.rps; i++) {
        const time = this.times[i];
        if (time === 0) return 0;        // can go now - nothing better!
        if (time < 0) continue;          // previous not finished yet
        if (this.ts() < time + 1000) continue; // not yet
    
        if (best === -1) best = time;
        else best = Math.min(best, time);
      }
      
      return best;
    }
    
    
    HorsesHolder.prototype.ts = function() {
      return (new Date()).getTime();
    }
    
    
    HorsesHolder.prototype._execute = function(index) {
      this.times[index] = -1; // mark busy
      const job = this.queue.shift();
      this.inprogress.push(job);
    
      const self = this;
      
      job.promiseMaker()
      .then(function(r) {
        self.debug  &&  console.info("%s ms: [HH] Job done at index %d", self.ts(), index);
        job.resolve(r);
      })
      .catch(function(err){
        self.debug  &&  console.error("%s ms: [HH err] Error at index %d: %s", self.ts(), index, err.toString());
        job.reject(err);
      })
      .finally(function(){
        self.inprogress.splice( self.inprogress.indexOf(job), 1);
        self.times[index] = self.ts();
        setTimeout(() => self._ping(), 1000);
      });
    }
    
    export default HorsesHolder;


    Модуль работы с VK API:
    /*global VK*/
    /**
     * Function returns Promise for each VK API call.
     * Respects the 3 call per second limit.
     *
     * by Sergei Sokolov <hello@sergeisokolov.com> 2019.
     */
     
    import HorsesHolder from '@/utils/horsesholder';
    
    const debug = true;
    
    const HH = new HorsesHolder({ debug });
    
    
    export default function asyncVK(methodName, data) {
    
    	return HH.add(() => {
    
    		data = data || {};
    		if (!data.v) data.v = 5.92; // VK API version https://vk.com/dev/versions
    		
    		return new Promise((res, rej) => {
    			VK.Api.call(
    				methodName,
    				data,
    				r => {
    					if (r.error) {
    						debug && console.error("[asyncvk] VK API call error:", r.error);
    					}
    					
    					
    					if (r.response) {
    						
    						res(r.response);
    						
    					} else if (r.error) {
    						
    						rej(r.error);
    						
    					} else {
    						
    						debug && console.error("[asyncvk] VK API bad response:", r);
    						
    						rej(r);
    						
    					}
    				}
    			)
    		});
    	});
    }


    Ответ написан
    1 комментарий
  • Почему не выводятся на экран числа массива с помощью цикла for?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    первый вариант:

    var mass = [1,2,3,4,5,6,7,8,9,10];
    for(i=0;i<mass.length;i++){
        document.getElementById('root').innerHTML += mass[i];
    }


    второй вариант:

    var r = document.getElementById('root');
    var mass = [1,2,3,4,5,6,7,8,9,10];
    for(i=0;i<mass.length;i++){
        r.innerHTML += mass[i];
    }


    Но разумеется можно короче
    var mass = [1,2,3,4,5,6,7,8,9,10];
    for (document.getElementById("root").innerHTML = mass.join(","); 0;)
    Ответ написан
    Комментировать
  • Возможно ли при клике сэмулировать двойнок клик?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Ваниль:
    document.getElementById("tot-block")
      .addEventListener("click", e => e.target.dispatchEvent(
        new MouseEvent('dblclick', {
          'view': window,
          'bubbles': true,
          'cancelable': true
        })
      )
    );


    ⚠️ Любое событие, сгенерированное скриптом, отличается от «честного» действия пользователя свойством события isTrusted.
    Ответ написан
    Комментировать
  • Какие есть способы округлить число на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const roundigit = digit => {
      if (1!==digit.toString().length||!Number.isFinite(digit))throw "Не цифра!";return digit;}

    spoiler
    Цифра - это 0, 1,2,3,4,5,6,7,8 или 9 - каждая их них целая. Можно не округлять. Расходимся.


    если серьёзно
    Чтобы в сторону нуля округлять, вариант:
    const floor = x => x | 0;
    Ответ написан
    2 комментария
  • VK api. Как получить json всех Олегов из города Кукуева?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вероятная причина ошибки

    Метод users.get() можно вызывать с ключом одного из трёх типов:
    • сервисный ключ (приложения)
    • ключ сообщества
    • ключ пользователя
    в то время, как users.search() можно вызывать только с ключом пользователя.

    Раз users.get() срабатывает , а на users.search() возвращается ошибка токена, вероятнее всего используется токен Сообщества или Сервисный ключ приложения.

    Что делать

    Получите ключ Пользователя. Для этого понадобится создать своё приложение ВК или использовать уже готовое. Специальных прав запрашивать не нужно, просто получить токен.

    В запросе к users.search() для поиска только в городе N, понадобится найти сначала id этого города N в Справочнике городов ВК. Для этого есть метод database.getCities() - клик по ссылке (внизу страницы) выполнит поиск и вернет несколько населенных пунктов, похожих на «Кукуево», у каждого свой id.

    Итого, в метод users.search() вы передадите следующие параметры:
    1. v=5.101 — версия API, обязательный
    2. access_token=XXXXX — токен Пользователя в любом приложении ВК
    3. count=1000 — без этого параметра вернёт только 20 результатов
    4. q=Олег — поисковая строка
    5. city=123 — id города Кукуево, полученный ранее в database.getCities()
    6. sex=2 — мужской пол (необязательно)
    7. age_from=18 — искомый Олег закончил школу
    8. age_to=24 — наверное, искомый Олег ещё не получает пенсию
    Ответ написан
    3 комментария
  • Как использовать строковые методы и выведите "tetsetesesesesteest"?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Строку собирайте по частям. Пригодятся эти семь методов объекта String:
    Примените каждый из них, чтобы получить часть результата.

    Например, так
    const x = "test";
    const result = ''
      + x.substr(0, 2) // te
      + x.split('').reverse().join('') // tset
      + x.substring(1,3).repeat(4) // eseseses
      + x.substring(0,2) // te
      + x.substring(1)   // est
    ; // tetsetesesesesteest

    Но здесь «незаконно» используется преобразование к Array для отзеркаливания строки "test" -> "tset".

    Задача творческая и довольно забавная. Проявите себя и найдите какой-то оригинальный способ.
    Ответ написан
    Комментировать
  • Как передать индекс цикла внутрь него другому массиву?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    К изучению: замыкания в JS.

    С минимальными изменениями можно примерно так сделать функцию, создающую функции, каждая запоминает переданный i:
    плохой код
    const slides = document.querySelectorAll('.reviews__item');
    var radioButtons = document.getElementsByName('review-toggle');
    var makeListener = function(i) {
      return function (evt) {
        evt.preventDefault;
        for (var j = 0; slides.length > j; j++) {
          slides[j].classList.add('slider__item--hidden');
        };
        slides[i].classList.remove('slider__item--hidden');
      };
    }
    
    for (var i = 0; i < radioButtons.length; i++) {
      radioButtons[i].addEventListener ('click', makeListener(i));
    };


    Лучше так:
    Ответ написан
    Комментировать
  • Удалить лишние знаки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const f = n => parseFloat(n.toFixed(5));
    
    // Tests:
    f(1) // 1
    f(1.12) // 1.12
    f(1.1234567890) // 1.12346
    f(000001) // 1
    f(100000) // 100000
    f(-1e5) // -100000


    Upd. Если обязательно именно отбросить без округления, то надо работать как со строками:
    (()=>{
      
    const f = x => {
      const n = parseFloat(+x);
      const sign = Math.sign(n);
      // отсечь экпоненциальную запись (0.0000001).toString() === "1e-7"
      if (Math.abs(n) < 1e-5) return 0; 
      return sign * parseFloat(x)
        .toString()
        .split('.')
        .map((n,i) => i ? n.substring(0,5) : parseInt(n))
        .join('.');
    }
    
    // Tests:
    ['0000001', '0.0000101', 1.000000001,  -1e-4, -1e-5, -1e-6, 1e5, Math.E, 1, -1, 0, false, ]
      .map(n => `${n} // ${f(n)}`)
      .join('\n');
    /*
    0000001 // 1
    0.0000101 // 0.00001
    1.000000001 // 1
    -0.0001 // -0.0001
    -0.00001 // -0.00001
    -0.000001 // 0
    100000 // 100000
    2.718281828459045 // 2.71828
    1 // 1
    -1 // 1
    0 // 0
    false // 0
    */
    Ответ написан
  • Как выполнить JS код после загрузки страницы?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    См. подробнее про загрузку скриптов с async и defer

    // вызовет initialize только когда догрузятся все скрипты defer:
    document.addEventListener('DOMContentLoaded', initialize);
    Ответ написан
    1 комментарий
  • Что такое коллекция в JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Четкого определения «collection» в JavaScript не встречал. Интуитивно, коллекция это структура данных для хранения нескольких значений.

    Объект и массив, по-моему, можно отнести к коллекциям.

    В ES6 появились два новых типа данных – Map и Set, которые тоже можно отнести к «коллекциям». В переводе на Русский язык словом «Коллекция» назвали из них именно Set, предназначенный для хранения только уникальных значений. Но я бы не считал требование уникальности значений отличительным признаком «коллекций» вообще.
    Ответ написан
    2 комментария