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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    1. Не «внутри» друг друга. Метод вызывается у объекта.

    document.getElementById() – это метод getElementById() у объекта document. Вызов возвращает Element. Или null, если нет элемента с таким ID.

    Второй вызов – пытаетесь вызвать метод getElementById() уже у объекта Element. А у него такого метода нет.

    2. Не «поисковые» методы. document.getElementById() не ищет, а просто берёт, если есть такой.
    Ответ написан
    Комментировать
  • Почему не удаляется обработчик события клика?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Метод bind() создаёт каждый раз новую копию функции.

    Для отмены слушателя нужно передать именно действующий обработчик, а не похожий.
    Запишите его в переменную и далее действуйте с переменной:
    const listener = this.onclickWindowHandler.bind(this);
    window.addEventListener('click', listener);
    // ...
    window.removeEventListener('click', listener);
    Ответ написан
    Комментировать
  • Приоритет выполнения операндов и операторов. Почему так происходит?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Разница в примерах – в возвращаемом значении:
    • alert(value) возвращает undefined
    • myalert(value) возвращает value


    Выражение A || B && C разбирается как A || (B && C)

    Сначала оценивается A. Если оно приводится к false, требуется проверить второй аргумент ||, т.е. (B && C)
    Сначала проверяется B. Если оно приводится к false, то проверять C уже не нужно.
    Ответ написан
    5 комментариев
  • Сортировка html блоков JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Собрать все блоки в словарь, где ключ - слово, значение - этот блок.
    Ключи отсортировать.
    Расставить блоки назад в родителя первого из них.
    код JavaScript
    function resort(selector) {
    	const nodeList = document.querySelectorAll(selector);
      const dict = {};
      const parent = nodeList[0].parentNode;
      nodeList.forEach(node => {
      	const key = node.querySelector('p').innerText;
        dict[key] = node;
        node.parentNode.removeChild(node);
      });
      const keys = Object.keys(dict);
      keys.sort().forEach(k => parent.appendChild(dict[k]));
    }
    
    resort('.slide');


    Работающий пример:
    Ответ написан
    1 комментарий
  • Как быстро найти подстроку в строке?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Решил топорно, по времени проходит. Но там такие крутые решения короткие в топе!

    Обходить массив слов достаточно один раз.
    Очередное слово может найтись в target в нулевой позиции - тогда оно "первое", или в другой, тогда надо проверить что та позиция + длина слова точно достают до конца target.
    Складывать в массивы позицию подходящего слова и длину искомого другого слова.
    Нашли очереденое Начальное слово - смотрим, есть ли ему соотв. искомая длина среди найденных Конечных.
    Нашли очередное Конечное слово - смотрим, есть ли соответствующее ему по искомой длине Начальное среди уже найденных.
    Как только нашлась пара - возвращаем ответ.

    мое так-себе решение
    function fn(words, target) {
      
      const length = words.length, targetLength = target.length;
      
      const aWord = [];   // индексы слов в aWords
      const aWant = [];   // какой длины не хватает до целого
      
      const bWord = [];
      const bWant = [];
    
    
      for (let i = 0; i < length; i++) {
    
        const word = words[i];
    
        const x = target.indexOf(word);
        if (-1 === x) continue;
        
        const wordLength = word.length;
        const want = targetLength - wordLength;
    
        if (x === 0) { // в начале составного, первое подслово
          
          aWord.push(i);
          aWant.push(want);
          
          const bIndex = bWant.indexOf(wordLength);
          if (-1 === bIndex) continue;
          
          const bWordIndex = bWord[bIndex];
          return [words[bWordIndex], word, [i, bWordIndex]];
          
        } else { // не в начале слова встретилось - второе слово, в конце цели
          
          if (x + wordLength !== targetLength) continue; // не попадает в конец
          
          bWord.push(i);
          bWant.push(want);
          
          const aIndex = aWant.indexOf(wordLength);
          
          if (-1 === aIndex) continue;
          const aWordIndex = aWord[aIndex];
          return [words[aWordIndex], word, [aWordIndex, i]];
    
        }
      }
      
      return null;
    }
    крутая идея в топе

    Бить целевое слово во всех возможных вариантах пар - а их даже меньше, чем длина целевого слова!
    Искать каждые два слова в данном массиве. Если оба нашлись, вот оно, решение.
    В 8 строк. Если поджать форматирование, то в 6.
    Ответ написан
    2 комментария
  • Как отследить момент столкновения?

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

    Запоминайте где-то "текущее" состояние
    var isCollided = false; // изначально нет столкновения
    На каждой итерации – будь то по setInterval() или requestAnimationFrame() – проверяйте, есть ли столкновение сейчас. И сравнивайте с предыдущим.
    const isNowCollided = checkIfCollided(); // как-то проверяем, есть ли сейчас наложение
    if (isNowCollided && !isCollided) { // впервые столкнулись!
      // alert! alert!
    } else if (!isNowCollided && isCollided) { // выехали из зоны
      // всем неинтересно
    } else {
      // вообще без новостей
    }
    
    isCollided = isNowCollided;
    Ответ написан
    Комментировать
  • Срабатывание строки кода не более раза в n секунд?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Запоминать где-то время создания "объекта".
    При очередном клике смотреть, прошло ли достаточное время (или время ещё не записано), иначе игнорировать.
    Ответ написан
    Комментировать
  • Как по клику найти индекс элемента среди его соседей?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    document.querySelectorAll('.slide').forEach(
    	(el, i) => el.addEventListener('click', () => console.log(1+i))
    )


    Ответ написан
    Комментировать
  • Как в разные div'ы вставлять разные рандомные картинки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В этой задаче хорошо бы генерить случайные числа без повтора максимально долго. Исчерпывать последовательность 0..n, в случайном порядке выдёргивая из этой «колоды» очередную карту. Когда колода пустеет, открываем новую.

    Можно примерно так сделать функцию, которая будет выдёргивать из колоды случайную карту, и другой функцией генерить для неё картинку:
    // Итератор случайных уникальных - Random Unique
    function getRUIterator(max) {
      let buffer = [];
      
      const ruIterator = {
        next: function() {
          if (buffer.length === 0) { // если колода пуста
            for (let i = 0; i < max; i++) buffer.push(i); // открываем новую 0..max
          }
    
          const index = Math.floor(Math.random() * buffer.length);
          return buffer.splice(index, 1)[0]; // вынимаем из колоды случайную карту
        }
      }
      
      return ruIterator;
    }
    
    /**
     * генерим в каждый див по случайной картинке
     * как можно дольше без повторов
     * @param int iTotal число доступных картинок
     * @param Array массив строк - айдишки div'ов, куда вставлять
     */
    function placeRandomImages(iTotal, aDivs) {  
      function placeImage(n, id) {
        const img = new Image();
        img.src = `img/${n}.png`;
        img.border = '0';
        document.getElementById(id).appendChild(img);
      }
      
      // будет генерить случайные неповторяющиеся
      const RUI = getRUIterator(iTotal);
      
      for (let i = 0; i < aDivs.length) {
        placeImage( RUI(), aDivs[i]);
      }
    }
    
    placeRandomImages(2, ["imaaaga", "imaaaga2"]);
    Ответ написан
    Комментировать
  • Можете пояснить логику вызова функции по завершению асинхронной загрузки внешнего скрипта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Не нашёл, как называется такой паттерн. Попробую объяснить, как я понимаю этот код.

    Во время выполнения кода неизвестно, определён ли уже глобальный объект. У глобального должен быть метод push(), принимающий пачку новых параметров. Но мы готовы к обоим вариантам: пушим или в крутой объект, или в пустой массив.

    После загрузки внешнего скрипта, тот смотрит, пусто ли глобальное свойство, на которое он претендует. Если не пусто - там накопились данные для него и он их себе записывает куда надо при инициализации. Примерно так:
    (function(w, n) {
      w[n] = w[n] || [];
      w[n].push({a: "A", b: "B"});
    })(window, 'tosterQuery');
    
    
    
    // в скрипте подгружаемом позже
    (function(w, n) {
      // не перезаписать объкт. Только если пустой или массив.
      if (w[n] && !Array.isArray(w[n])) return;
        
      function f() {
        const data = w[n] || [];
        // определяем свой push с блекджеком
        this.push = function(x) {return data.push(x);}
        this.getData = function() {return data;}
      }
     
      w[n] = new f(); // занимаем глобальное свойство
    })(window, 'tosterQuery');
    
    tosterQuery.getData(); //  [{"a":"A","b":"B"}]
    tosterQuery.push({z:"Z"});
    tosterQuery.getData(); //  [{"a":"A","b":"B"}, {"z":"Z"}]
    Ответ написан
    1 комментарий
  • Какие сайты с тестами по JS вы знаете?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    CodeWars

    Там не только JS, есть и многие другие языки.
    Ответ написан
    Комментировать
  • Как лучше оптимизировать и сделать мой код на JavaScript красивее и короче?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Если это практическая задача, а не собеседование с глубоко зарытыми подвохами, то так:
    if (!roofpt) Price2 = 5500; // null, 0, undefined, false, пустая строка
    else if (roofmat == 1) Price2 = 7900; // и так известно, что не пустое
    else if (roofmat == 2) Price2 = 8900; // и так известно, что не пустое
    else Price2 = 0; // по умолчанию

    Если же это из собеседования

    В исходном коде есть такая деталь. Приоритет операторов в JS ставит && выше, чем ||. Эти два условия выглядят похоже, имелась в виду, наверное, лишняя перепроверка на null/ноль:
    (roofpt  == null || roofpt  == 0) 
    (roofpt !== null || roofpt !== 0 && roofmat == 1)


    Но сначала &&, потом ||:
    A || B && C === A  ||  (B && C)
    // и второе условие на деле считается так:
    (roofpt !== null || (roofpt !== 0 && roofmat == 1))

    Т.е. второе условие выполнится и просто при любом rootpt, неравном null.

    Тут же ещё одна деталь. Нестрогое равенство == и строгое неравенство !==. Разжёвывать не буду, чтобы вы провалили собеседование.
    Ответ написан
    1 комментарий
  • Как оптимизировать и сократить код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Описаны последовательные отрезки якобы непрерывного диапазона. Косяк в том, что для значений между, скажем, 120 и 120.001, условия не определены и код даст ошибку, т.к. не определится одна из переменных.

    Поэтому лучше цепочка else if. Поскольку они перемножаются и по умолчанию единицы, можно сразу определять конечное значение:

    if (floors.value == 1) {
    
      aF = 1; // по умолчанию, для больше 300
      
      if (area.value <= 120) aF = 1.26;
      else if (area.value <= 140) aF = 1.24;
      else if (area.value <= 160) aF = 1.23;
      else if (area.value <= 200) aF = 1.22;
      else if (area.value <= 260) aF = 1.2;
      else if (area.value <= 300) aF = 1.19;
    
      console.log(aF);
      
    } else if (floors.value == 2 || floors.value == 3) {
      
      bF = 1; // ? для меньше 100 .. и больше 300
      
      if (area.value >= 100 && area.value <= 130) bF = 1.3;
      else if (area.value <= 160) bF = 1.27;
      else if (area.value <= 200) bF = 1.24;
      else if (area.value <= 300) bF = 1.22;
    
      console.log(bF);
    
    }
    Ответ написан
    Комментировать
  • Как обнулить таймер при достижении 31?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В датах JavaScript, так уж повелось, месяца считаются от 0 (январь) до 11 (декабрь), в то время, как годы и даты (дни месяца) считаются по-человечески, как пишутся.

    Это и удобно, когда делаете массив с именами для месяцев, не нужно пустой элемент в начале укладывать. Просто:
    const monthNames = 'января февраля марта апреля мая июня июля августа сентября октября ноября декабря'
      .split(' '); // получится массив
    const D = new Date(); // объект Даты на сейчас
    
    // завтрашний день
    D.setDate( D.getDate() + 1); // так месяц "переключится" автомагически
    console.log( 'Завтра ' + D.getDate() + ' ' + monthNames[ D.getMonth() ] );
    Ответ написан
    Комментировать
  • Как проверить GET запрос?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно проверять свойства элемента complete и после него naturalWidth (или naturalHeight) через какое-то время после назначения src – достаточное для загрузки картинки. Проверка того, есть ли картинка, в любом случае немгновенна, асихнонна.

    const srcs = [
        'https://sun6-5.userapi.com/c850632/v850632804/12d149/KnY01pJH16w.jpg'
        ,'https://sun6-6.userapi.com/c855020/v855020551/59a81/phM3k4nXcrg.jpg'
      ];
      
      function makeCheck(image) {
        return function() {
          if (image.complete  &&  image.naturalWidth) {
            console.log("картинка загрузилась ОК!");
          } else {
            console.error("Нет такой картинки: " + image.src);
          }
        }
      }
      
      for(let i = 0;i < srcs.length; i++) {
        const src = srcs[i];
        const image = new Image();
        window.setTimeout( makeCheck(image), 300);
    
    //image.src = "../img/designers/" + index + '.' + id + ".jpg";
        image.src = src;
      }
    Ответ написан
    Комментировать
  • Как сделать, чтобы вложенная окружность убегала от курсора?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Чтобы пример заработал, надо в Settings - JavaScript - включить препроцессор Babel.

    По событию движения мыши, надо кругу давать координаты самой дальней точки у окружности. Для этого понадобится вектор от курсора к центру. И продлить его на радиус.

    Примерно так:


    По-хорошему, наверное, надо после первого же движения мышки "прилеплять" круг к противоположной стенке, и дальнейшие движения делать скользящими по окружности, т.к. нет сил, способных отодрать шарик от стенки.
    Ответ написан
  • Как посчитать сколько раз цифра повторяется в числе?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно без регулярных выражений, которые под капотом нелегки, старым добрым indexOf() в лоб. Костыль только для двух повторов, но, по идее, быстрее регулярок:

    function haz2ones(str) {
        const s = str.toString();
        const search = '1';
    
        let i = s.indexOf(search);
        if (!~i) return false;
    
        i = s.indexOf(search, i + 1);
        if (!i) return false;
        if (!!~s.indexOf(search, i + 1)) return false;
        return true;
      }

    Тесты
    const tests = [
        [1, false],
        [11, true],
        [111, false],
        ['1', false],
        ['11', true],
        ['111', false],
        ['100001', true],
        ['000011', true],
        [12345678901234567890, true],
      ];
      
      return tests.map(e => haz2ones(e[0]) === e[1] ? '+' : '- ' + e[0]);
      // +,+,+,+,+,+,+,+,+
    Ответ написан
    Комментировать
  • JQuery. Как добавить недостающий класс?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    просто добавить класс addClass() последнему элементу :last-child

    $('.parent div:last-child').addClass('div2');
    Ответ написан
  • Является ли данный пример замыканием и почему ДА или НЕТ?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Mozilla определяет замыкания так:
    Замыкание — это комбинация функции и лексического окружения, в котором эта функция была определена.
    A closure is the combination of a function and the lexical environment within which that function was declared.

    Если эти вводные описания посчитать за «правильные» определения, то формально «ДА», является, хоть и вырожденным. В вашем примере это окружение совпадает с глобальным, поэтому ни о какой имитации приватных методов и свойств тут речи не идёт.

    Чтобы сделать кошерное замыкание надо как следует обернуть сей код, чтобы в приватность его переменных никто извне не мог добраться:
    function makeCounter() {
      // далее ваш код:
      let count = 0;
      function counter() {
        return count += 1;
      }
      // конец вашего кода.
    
      return counter; // вернули Функцию (с её окружением)
    }
    
    var myCounter = makeCounter();
    // вот теперь к значению count не добраться - приватность!
    // зато
    console.log(myCounter()); // 1
    console.log(myCounter()); // 2
    console.log(myCounter()); // 3
    Ответ написан
    6 комментариев
  • Как создать циклическую анимацию на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Может, лучше без JS сделать средствами CSS?
    @keyframes swing {
      0% {transform: rotate(-15deg)}
      50% {transform: rotate(15deg)}
      100% {transform: rotate(-15deg)}
    }


    Ответ написан
    3 комментария