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

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Применяется подход, я бы его назвал "отбрасывание хвоста", но возможно есть и официальное название. Работает внутри функции в виде досрочного выхода из неё.

    При if и if-else нужно как бы помнить все предыдущие if и держать их в голове. При отбрасывании хвоста всё наоборот - разум очищается, отработанные мысли выкидываются, и в голове обычно 1-2 условия нужно держать.

    Подход можно применить частично, потому что это может быть не тупая колбаса условий if, а else-ветвистая. Но каждую линейную ветвь точно можно превращать в маленький хвостик, а если рефакторить, то и ветки побольше. Главное, всё время стараться избавиться от лишнего ментального груза. Тогда код превращается в обычную прозу, где инструкции следуют одна за другой (императивно) без сложной многоступенчатой логики, и его становится легко читать и понимать.

    Для if:
    Конструкция
    if (condition_A) {
      instruction_A;
      if (condition_B) {
        instruction_B;
        if (condition_C) {
          instruction_C;
          .....
        }
      }
    }

    Превращается в (вложенности уходят):
    if (!condition_A) return;
    instruction_A;
    if (!condition_B) return;
    instruction_B;
    if (!condition_C) return;
    instruction_C;
    .....
    Для if-else:
    Конструкция
    if (condition_A) {
      instruction_A;
    } else if (condition_B) {
      instruction_B;
    } else if (condition_C) {
      instruction_C;
    } else if .....

    Превращается в обычный switch, либо снова в отбрасывание хвоста:
    if (condition_A) {
      instruction_A;
      return;
    }
    if (condition_B) {
      instruction_B;
      return;
    }
    if (condition_C) {
      instruction_C;
      return;
    }
    if .....


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

    Конечно, если есть повторы в условиях, как у вас, то можно как-то сообразить, как это представить в виде цикла (обхода массива любым способом), или скомбинировать разные ветки условий в одну с помощью && и ||, или опять-таки выделить в подфункцию. Сообразить = рефакторить. Обработку ошибок можно также оборачивать в try-catch, но это уже другая история.
    Ответ написан
  • Почему событие отслеживается только при клике в определенном месте div?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    ".modale_cart" - это другой див, а не тот, который содержит иконку.
    Где-то в вашей структуре вложенности дивов есть элемент, который тоже отслеживает клик, но не передаёт его дальше по цепочке, а как бы съедает (оставляет инфу о клике только себе, монопольно).

    Ищите, смотрите другие обработчики. Наверняка там что-то типа:
    .stopPropagation()

    P.S. Ссылка по теме: https://learn.javascript.ru/event-delegation
    Ответ написан
    Комментировать
  • Как собрать в массив информацию из DOM-элементов?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Например так:
    let b = Array.from(a.querySelectorAll('div.name'));
    let c = Array.from(a.querySelector('div.name'));
    
    //a[0].innerHTML
    //b[0].innerHTML
    //c.innerHTML
    Ответ написан
    Комментировать
  • Почему строка инициализируется как число?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Дело в том, что вы вырезаете из массива кусочек.
    В результате длина массива меняется, и после вырезанного всё сдвигается.
    Меняются и индексы.

    Решение:
    После splice добавьте: i--;

    Либо перебирайте массив с конца:
    for(let i = l.length-1; i >=0; i--) {
    Ответ написан
  • Почему мое условие на проверку ширины неправильно работает?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Если в будущем у меня будет мерседес, то выдайте мне ключи от него сейчас.
    Ответ написан
  • Как запретить удалять в инпуте первый символ?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Вынести его за пределы инпута.
    Как вариант - наложить его сверху полупрозрачностью, а текст внутри инпута сместить правее с помощью css.
    Ответ написан
    Комментировать
  • Почему такая очередь задач?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Попадает очередь в порядке вызова setTimeout, а не в порядке компиляции.
    Сначала вызывается timeout2, лишь потом срабатывает then и timeout1 вместе с ним.
    Ответ написан
    Комментировать
  • Разница между requestIdleCallback и setTimeout?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Для начала вам нужно понять главное: ложки «периода простоя» не существует.

    setTimeout() запускает код НЕ РАНЬШЕ, чем указанный в параметре интервал времени. Если указали 5000, то должно пройти не меньше 5 секунд.

    Если вы запустили таймер 5000, затем через секунду запустили таймер 2000, затем какая-то функция нагрузила браузер непрерывной работой на 10 секунд, то второй таймер будет иметь приоритет над первым, хотя и был создан позже первого.
    доказательство
    function sleep(ms) { //примерное время, CPU-зависимо
      let tm = performance.now();
      for (let i=0;i<1000000*ms;i++) { let x = i*i }
      console.log('sleep(' + (performance.now()-tm).toFixed() + ') - done.')
    }
    
    setTimeout(e=>console.log('first'), 5000);
    sleep(1000)
    setTimeout(e=>console.log('second'), 2000);
    sleep(9000)


    requestIdleCallback(), насколько я понимаю, вызывает код в ближайший «интервал простоя» в порядке очереди и код может быть вызван РАНЬШЕ указанного timeout (а может и позже, смотря когда будет «простой»).
    пример, когда после setTimeout
    function sleep(ms) { //примерное время, CPU-зависимо
      let tm = performance.now();
      for (let i=0;i<1000000*ms;i++) { let x = i*i }
      console.log('sleep(' + (performance.now()-tm).toFixed() + ') - done.')
    }
    
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    setTimeout(e=>sleep(1000),100);
    
    requestIdleCallback(e=>console.log('first'),{timeout:5000});
    requestIdleCallback(e=>console.log('second'),{timeout:4000});
    sleep(1000);
    пример со вклиниванием в очередь setTimeout
    function sleep(ms) { //примерное время, CPU-зависимо
      let tm = performance.now();
      for (let i=0;i<1000000*ms;i++) { let x = i*i }
      console.log('sleep(' + (performance.now()-tm).toFixed() + ') - done.')
    }
    
    setTimeout(e=>sleep(2000),0);
    setTimeout(e=>sleep(2000),1000);
    setTimeout(e=>sleep(2000),2000);
    setTimeout(e=>sleep(2000),3000);
    setTimeout(e=>sleep(2000),4000);
    setTimeout(e=>sleep(2000),5000);
    setTimeout(e=>sleep(2000),6000);
    setTimeout(e=>sleep(2000),7000);
    setTimeout(e=>sleep(2000),8000);
    setTimeout(e=>sleep(2000),9000);
    
    requestIdleCallback(e=>console.log('first'),{timeout:5000});
    requestIdleCallback(e=>console.log('second'),{timeout:1000});
    sleep(1000);
    пример, когда наступает «период простоя» до фактической разгрузки
    function sleep(ms) { //примерное время, CPU-зависимо
      let tm = performance.now();
      for (let i=0;i<1000000*ms;i++) { let x = i*i }
      console.log('sleep(' + (performance.now()-tm).toFixed() + ') - done.')
    }
    
    var cnt = 10;
    function timer() {
      sleep(1000);
      cnt--;
      if (cnt > 0) setTimeout(timer,300);
    }
    
    setTimeout(timer,300);
    
    requestIdleCallback(e=>console.log('first'),{timeout:5000});
    requestIdleCallback(e=>console.log('second'),{timeout:4000});
    sleep(1000);


    requestIdleCallback() рекомендуется использовать, когда время выполнения вам не критично, при этом вы не хотите тормозить анимации, нажатия на кнопки и пр. Это всякие не важные задачи.
    А setTimeout() лучше использовать тогда, когда вам нужно выполнить функцию через указанный интервал времени, но как можно скорее. Например, если от этого зависит контент на странице, без которого её отзывчивость не будет иметь смысла.
    Ответ написан
    Комментировать
  • Как правильно вернуть массив?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Как правильно вернуть массив?

    return final;
    Ответ написан
    Комментировать
  • Можете поверхностно сказать что делает код?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Это обфусцированный код. Из-за этого нельзя поверхностно взглянуть на код и сказать, что он делает. Только после анализа можно будет сказать. Автор кода хочет, чтобы даже анализ давался сложно, чтобы аналитик потратил много времени и в идеале - отказался от идеи вскрывать этот код.

    Поэтому ответ на вопрос: не можем.

    Если вы не разбираетесь вообще, то вам бегло смотреть нет смысла тем более. Связь с жсон и др. функциями - это ни о чём, потому что почти про любой js код можно так сказать.

    P.S. "Буквально минутку внимания" - риторика на уровне школьника, либо хитрого провокатора. И то, и другое - не в вашу пользу.
    Ответ написан
    Комментировать
  • Как вернуть первые N максимальных элементов из массива без сортировки массива?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Строго - никак.

    Есть разные алгоритмы частичной сортировки с минимальной сложность O(N+KlogN), где K - количество максимумов, а N - размер массива, но совсем без сортировки не получится в общем случае.

    Если не строго, то сильно зависит от специфики задачи, из которой нужно взять какие-то доп. условия и допущения. Именно они позволят оптимизировать алгоритм.

    Например, если K не строгое, а лишь примерное, то можно прикинуть некий порог, выше которого эти элементы будут расположены. Скажем, K=10, N=1000 элементов, и в каждом случайное число от 1 до 1000. Тогда можно почти уверенно заявить, что все искомые элементы больше 970. Пробегаем массив один раз и находим все элементы больше 970. Их окажется около 30 плюс-минус. Главное, что не менее 10. Далее этот маленький массив можно отсортировать, но это снова сортировка.
    Ответ написан
  • Как сделать чтобы рандом всегда давал новые значения?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    У вас переменная random (случайное число) генерируется единожды, и дальше используется при каждом нажатии на кнопку.

    Нужно поместить эту логику внутрь функции-обработчика нажатия на кнопку, то есть внутрь фигурных скобок {}. Тогда новое случайное число будет генерироваться при каждом нажатии на кнопку, что и даст разные значения.

    P.S. на заметку:
    На первое место выпадает шанс не 10%, а всего 5% случаев. И ещё 5% не будет попадать в границы массива, что будет приводить к ошибке.
    ((0.00)*10).toFixed() // "0"
    ((0.01)*10).toFixed() // "0"
    ((0.04)*10).toFixed() // "0"
    ((0.05)*10).toFixed() // "1"
    ((0.94)*10).toFixed() // "9"
    ((0.95)*10).toFixed() // "10"
    ((0.96)*10).toFixed() // "10"
    Ответ написан
    Комментировать
  • Почему условный тернарный оператор не возвращает нужное значение?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Потому что вы забыли написать return:
    (item, i) => {
      return (i == 0)? item : item[0].toUpperCase() + item.slice(1);
    }

    Ну либо можно убрать лишние фигурные скобки:
    (item, i) => (i == 0)? item : item[0].toUpperCase() + item.slice(1)
    Ответ написан
    1 комментарий
  • Почему данные с сервера приходят с null?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Проблема может быть в чём угодно на стороне сервера, но явно не в самих заголовках. Потому что json-ответ вы всё же получаете.

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

    dollar
    @dollar
    Делай добро и бросай его в воду.
    MutationObserver

    Ну либо костыль через setInterval().
    Ответ написан
    1 комментарий
  • Как округлить часть числа?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    я вроде как прописал tofixed

    Вроде как нужно прописывать в нужном месте, а не просто для галочки.

    Здесь вы присваиваете summ, а не summ.toFixed(2):
    domElements.rating.total.innerHTML=summ
    Ответ написан
    2 комментария
  • Как правильно анимировать элементы при помощи setInterval?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    ...методом setInterval к каждой картинке по отдельности...

    Вот здесь просчёт.

    Нужно отсчитывать временной интервал следующей картинки от предыдущей, а не от общего начала. Потому что на самом деле нет гарантии, сколько времени будет длится очередной таймаут. Если вы укажете 500мс, то это лишь означает не менее 500с, а в теории может быть и 1 сек, и 2 сек, и вообще сколько угодно. И чем дольше анимация, тем больше накапливается мелких ошибок, и тем заметнее визуальный рассинхрон.

    Подойдёт единый setInterval с общей логикой внутри. Либо цепочка из setTimeout, в которой одновременно запланирован только один.
    Ответ написан
  • Как сделать частично статичный текст в input?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    <input type="text" disabled>

    input1.disabled = true;
    Ответ написан
  • В чём ошибка в задаче?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Нельзя писать arg1 || arg2 != '', подобно кальке с русского языка.
    В программировании всё последовательно:
    • Либо сначала считает !=, а этот операнд имеет приоритет, поэтому если без скобок, то это эквивалентно такому: arg1 || (arg2 != ''). В этом случае мы проверяем, что arg2 не является пустой строкой. При этом он может быть символом или числом, например. ИЛИ arg1 является истинным.
    • Либо сначала считает ||, если иначе расставить скобки: (arg1 || arg2) != ''. В этом случае тоже ерунда какая-то. Мы проверяем истинность хотя бы одного аргумента, а потом зачем-то результат операции сравниваем с пустой строкой.


    Чтобы составить условие правильно, его нужно структурировать для понимания, то есть составление как бы разбить на этапы.
    1. Сначала нужно понять, как сформулировать простое условие "не является буквой". Условно запишем по-русски.
    2. Далее составляем следующее более сложное условие из кирпичиков, полученных на предыдущем этапе: (arg1 является буквой) && (arg2 является буквой). То есть для каждого аргумента повторяем выражение полностью. Если сомневаетесь в приоритетах вычислений, можно ещё и скобки расставить.


    Но вернёмся к началу. Вроде бы простое условие "arg является буковой", но готовой функции у нас нет. И чтобы проверить это утверждение, нужно проверить ещё более простые:
    1) что arg является строкой в принципе (не числом, не булевой переменной, не всякими там null и пр.)
    2) что эта строка имеет длину 1. Ведь если больше 1, то это уже не просто буква. А если меньше, то есть 0, то это тем более не буква.
    3) что оставшийся символ действительно является буквой. Не прибегая к регулярным выражениям (что для вас будет явно сложно), я бы схитрил так:
    arg==arg.toLowerCase() || arg==arg.toUpperCase()
    Обратите внимание на порядок операций. Сначала считаются сравнения, а потом они складываются через логическую операцию ИЛИ. То есть, если по-русски, мы записали, что символ равен самому себе в верхнем регистре, либо он равен самому себе в нижнем регистре. Это и будет означать, что это буква.

    Если же опустить предыдущие проверки, и допустить, например, что это длинная строка, например "абвгд", то у нас последнее утверждение окажется ошибочно верным, так что сначала нужно исключить всё лишнее.

    Ещё один совет: не обязательно городить бесконечный if else. Конечно, так тоже можно, но получается более громоздко и менее очевидно. Проще писать серию return'ов. Это всегда проще, а в вашем примере сам бог велел так делать. Пример:
    if (typeof arg1 != "string") return -1;
    if (arg1.length != 1) return -1;
    //и т.д.

    Здесь мы первой проверкой исключаем возможность, что это не строка. То есть если это не строка, то дальше выполнение функции не происходит, и мы сразу выходим. Поэтому во второй проверке уже можно быть точно уверенным, что arg1 - это строка, и исходить из этого. И весь код ниже тоже может рассчитывать, что arg1 - это строка длиной 1 символ, без вариантов.
    Ответ написан
    Комментировать
  • Как сгруппировать объекты в массиве?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Серьёзно? Это задача для начинающего.
    Императивно и в лоб: перебираете все элементы массива в цикле, по ходу дела создаёте нужные вам группы.
    как-то так
    let result = [];
    let num = 0;
    let obj;
    records.forEach(e => {
      if (num++ === 0) result.push(obj = {});
      Object.assign(obj, e);
      if (num === 5) num = 0;
    });
    console.log(result);
    //но можно сделать короче и красивее
    Ответ написан
    1 комментарий