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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Просто способ сделать код менее понятным человеку, в строках экранированные символы
    в формате \u#### записывается символ по коду в кодировке utf-16, где # - 16-ричная цифра
    в формате \x## записывается символ по коду в кодировке ASCII, где # - 16-ричная цифра

    Например строка '\u005fp\x6fp' - это закодированный вариант '_pop', в чем можно убедится, просто подставив ее в консоль браузера
    Ответ написан
    Комментировать
  • Как объединить отрезок кода в одну функцию?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const checkbox2tabMap = {
      link5: 'tab1',
      link6: 'tab2'
      // ... продолжите сами
    };
    function onCheckboxChange(event) {
      const tab = document.getElementById(checkbox2tabMap[event.target.id]);
      if(!tab) { return; }
      tab.style.display = event.target.checked ? 'block' : 'none';
    }
    Object.keys(checkbox2tabMap).forEach(
      id => document.getElementById(id).addEventListener('change', onCheckboxChange)
    );
    Ответ написан
    Комментировать
  • Почему не работает промис?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У вас функции bb принимает колбэк первым аргументом, а не последним, а полученный колбэк от обертки Вы никак не используете
    Ответ написан
  • Сделать каждую ссылку как кнопку?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function onLinkClick(event) {
      event.preventDefault(); // выключаем стандартный функционал браузера (переход)
      const {href} = event.target; // извлекли полный адрес из ссылки (даже для относительных ссылок вернет абсолютный адрес)
      const hrefAsInHTML = event.target.getAttribute('href'); // извлекли href таким какой он есть в html
      // любая Ваша логика
    }
    
    for(const link of document.getElementsByTagName('a')) {
      link.addEventListener('click', onLinkClick);
    }
    Ответ написан
    8 комментариев
  • Как создать экземпляр JS-класса в документе?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Webpack создает изолированную область видимости для каждого модуля. Вам нужно вручную положить Ваш класс в глобальный объект:
    class MyClass {
       constructor(){ this.init()}
       init () {}
    }
    
    // например вот так:
    window.MyClass = MyClass;
    Ответ написан
    Комментировать
  • Почему Cannot read property 'classList' of undefined?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Перенесите этот код из хука created в хук mounted
    Ответ написан
    Комментировать
  • Как во Vue игнорироть скобки, кавычки и тд в тексте?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Как и в обычном html, с помощью спец. символов
    Ответ написан
    Комментировать
  • Как загрузить файл на node.js сервер без сторонних библиотек?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В данном случае файл отправляется в теле запроса как есть, без всяких оберток:
    file_load.onsubmit = function(){
      var file = this.elements.myfile.files[0];
      var xhr = new XMLHttpRequest();
      xhr.open("POST", "upload", true);
      xhr.send(file);
      return false;
    }


    Следовательно на сервере нам достаточно перенаправить тело запроса целиком в файл:
    const server = require('http').createServer();
    const fs = require('fs');
    const nodeStatic = require('node-static');
    const file = new nodeStatic.Server('.', {
      cache: 0
    });
    
    server.listen(3000, () => console.log("сервер запущен"));
    server.on('request', (req, res) => {
      if (req.url == '/upload') {
        req.pipe(
          fs.createWriteStream('file2.jpg')
        ).on('finish', () => res.end('ok'));
        return;
      }
      file.serve(req, res);
    });
    Ответ написан
    1 комментарий
  • Как выполнять функцию через динамичные промежутки времени?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function setRandomInterval(cb, minDelay, maxDelay, ...args) {
        let timeoutID;
        (function next() {
            const delay = Math.floor(Math.random() * (maxDelay - minDelay) + minDelay);
            timeoutID = setTimeout(() => {
                cb(...args);
                next();
            }, delay);
        })();
        return function cancel() {
            clearTimeout(timeoutID);
        };
    }
    
    // использование:
    setRandomInterval(func, 500, 2500); // просто запускаем с интервалом от 0.5с до 2.5с
    const cancelInteraval = setRandomInterval(() => {
        console.log('it work');
        if(Math.random() > 0.7) {
            cancelInteraval(); // таймаут можно отменить если вызвать возвращенную функцию
        }
    }, 200, 500);
    setRandomInterval((arg1, arg2, arg3) => {
        console.log(arg1, arg2, arg3);
    }, 1000, 3000, 'arg1', 'arg2', 'arg3'); // подобно setTimeout и setInterval можно передать аргументы в колбэк
    Ответ написан
    Комментировать
  • Как правильно упростить запись в блоке for?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    for(let  i = Math.sign(number) || 1; Math.abs(i) < Math.abs(number); i += Math.sign(number) || 1) {
      // ...
    }
    Ответ написан
  • Как найти уникальные значения именно с помощью метода .find?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Например так:
    [1,2,3,1,2,3,4,0,-1].filter(function(el) {
      return !this.find(el2 => el === el2) && (this.push(el), true);
    }, [])
    Ответ написан
    Комментировать
  • Blob возвращает пустое изображение, как решить?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Отрисовка на канвасе идет после загрузки изображения
    А запрос на извлечение блоба идет до загрузки изображения и следовательно до отрисовки его на канвасе
    parent.querySelectorAll('.gallery-uploads-imgs__item').forEach(element => {
              var img = new Image;
              img.src = element.dataset.src
              document.body.append(img)
    
    
    
              let canvas = document.createElement('canvas')
              let context = canvas.getContext('2d');
              canvas.width = img.clientWidth
              canvas.height = img.clientHeight
    
    
              img.onload = function() {
                context.drawImage(img, 0,0);
                img.remove();
                canvas.toBlob(function(blob) {
                  let uploadImageUrl = URL.createObjectURL(blob);
    
                  data.blobs.push( uploadImageUrl )
    
                }, 'image/png');
              }    
            })


    P.S. вангую следующий вопрос будет в стиле data.blobs пустой...
    Ответ написан
  • Как добавить циклом for в пустой массив элементы - числа от 4 до 400, а потом уже когда в массиве будут эти элементы вывести их на экран?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    И вообще какие еще варианты могут быть решения этой задачи? Кроме цикла for? Несмотря на то что в задании пишет именно с помощью него решить задачу. Просто для себя чтобы знать другие варианты.
    document.getElementById('root').appendChild(
      document.createTextNode(
        Array.from(new Array(401), (_, i) => i).slice(4).join(' ')
      )
    );
    Ответ написан
    Комментировать
  • Как передать параметры в функцию при её импорте?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    import logBuilder from "./logs/logger";
    const log = logBuilder(import.meta);

    вот только в es-модулях нет предобъявленной переменной module, которая создается окружением commonjs модулей, но наверняка билдеру нужны метаданные, которые можно получить из import.meta
    Ответ написан
    Комментировать
  • Как извлечь три ветви JSON?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    response.items[0].id
    у Вас items - массив, в котором уже лежит объект с полем id
    Ответ написан
    3 комментария
  • Как присвоить объект по значению, а не по ссылке?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вам определенно нужен deepClone
    Можно взять готовый например из lodash, но я бы предложил Вам свою реализацию.
    Пока писал ее в ответ, понял, что в очередной раз мой ответ превращается в целую статью, поэтому разместил ее на хабре: https://habr.com/ru/post/466535/

    Ну или можете просто скопировать код и использовать:
    function deepClone(source) {
    	return ({
    		'object': cloneObject,
    		'function': cloneFunction
    	}[typeof source] || clonePrimitive)(source)();
    }
    
    function cloneObject(source) {
    	return (Array.isArray(source)
    		? () => source.map(deepClone)
    		: clonePrototype(source, cloneFields(source, simpleFunctor({})))
    	);
    }
    
    function cloneFunction(source) {
    	return cloneFields(source, simpleFunctor(function() {
    		return source.apply(this, arguments);
    	}));
    }
    
    function clonePrimitive(source) {
    	return () => source;
    }
    
    function simpleFunctor(value) {
    	return mapper => mapper ? simpleFunctor(mapper(value)) : value;
    }
    
    function makeCloneFieldReducer(source) {
    	return (destinationFunctor, field) => {
    		const descriptor = Object.getOwnPropertyDescriptor(source, field);
    		return destinationFunctor(destination => Object.defineProperty(destination, field, 'value' in descriptor ? {
    			...descriptor,
    			value: deepClone(descriptor.value)
    		} : descriptor));
    	};
    }
    
    function cloneFields(source, destinationFunctor) {
    	return (Object.getOwnPropertyNames(source)
    		.concat(Object.getOwnPropertySymbols(source))
    		.reduce(makeCloneFieldReducer(source), destinationFunctor)
    	);
    }
    
    function clonePrototype(source, destinationFunctor) {
    	return destinationFunctor(destination => Object.setPrototypeOf(destination, Object.getPrototypeOf(source)));
    }
    Ответ написан
    Комментировать
  • Можно ли отловить событие из vue компонента в нативном js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    import Vue from 'vue';
    import Component from './Component.vue';
    
    const component = new Vue(Component).$mount('selector');
    component.$on('event-name', () => console.log('wow'));
    Ответ написан
    9 комментариев
  • Как изменить стили через javascript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    var el = document.querySelector("a[href='/products/962112']"); // в селекторе хардкод... не будет ссылки с таким href - все сломается
    
    // тут был цикл, но я его убрал, ибо один элемент берем
    
    var products = document.getElementsByClassName('product'); // тут коллекция, ее надо перебирать циклом
    for(var i = 0; i < products.length; i++) {
      products[i].style.height = el.style.height;
    }


    UPD: по просьбе origami1024 добавляю вариант с CSSOM
    Во-первых, нам понадобится новый элемент style, чей CSSOM мы будем править, его стоит разместить ниже других стилевых подключений (не важно через style или link), я же просто добавлю в конец head
    Сам CSSOM элемента style доступен через его свойство sheet - извлеку его сразу в переменную:
    const {sheet} = document.head.appendChild(document.createElement('style'));

    Во-вторых, в CSSOM правила пронумерованы с 0. Притом можно заменять существующие правила по их индексу, а можно вставлять новые в конец (индекс при этом так же нужно указывать, а если указать неверно - выкинет эксэпшн). Нам же удобнее обращаться к правилам по селектору, поэтому я сделаю объект для сопоставления селектора с индексом правила и счетчик индексов:
    const rulesIndexesBySelector = {};
    let nextIndex = 0;

    Ну и наконец реализуем вспомогательную функцию для обновления CSSOM правила по его селектору:
    function updateRule(selector, declarations) {
      const rule = `${selector}{${declarations}}`; // полное правило - селектор + декларации в {}
      if(selector in rulesIndexesBySelector) {
        // индекс селектора уже известен, обновим правило
        const index = rulesIndexesBySelector[selector];
        sheet.deleteRule(index); // сначала удалим старое правило освободив индекс и отменив его свойства
        sheet.insertRule(rule, index); // и вставим на его место новое
      } else {
        // новый селектор
        const index = nextIndex++; // важен именно постинкримент, чтоб самый первый получил 0, второй 1 и т.д.
        rulesIndexesBySelector[selector] = index; // запомним на будущее
        sheet.insertRule(rule, index); // и вставим правило в конец
      }
    }

    Пример примитивный, но каждый думаю спокойно расширит его под себя.
    У меня например declarations собираются из vue объекта, который можно мутировать (реактивные стили оО) + добавляются вендорные префиксы, если браузер не знает каких-то свойств (не автопрефиксер конечно, но зато работает по месту)

    Использовать это все теперь можно крайне просто:
    updateRule('.product', 'height: 40px; width: 50px');
    Ответ написан
    5 комментариев
  • Как удалить внешний блок?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const elem = document.querySelector('.one');
    const frag = document.createDocumentFragment();
    for(const child of elem.childNodes) {
      frag.appendChild(child);
    }
    elem.parentElement.replaceChild(frag, elem);
    Ответ написан
  • Как вызвать функцию через 5 секунд после клика?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Функция up должна корректно решать поставленную задачу
    Скорее всего проблема в обработчике события.
    Атрибуты вроде onclick работают только с глобальным контекстом, лучше их не использовать

    Правильнее выбрать input из DOM (например с помощью document.querySelector) и навешать обработчик через метод элемента addEventListener

    Так же важно помнить, что выбор элемента нужно делать после того, как он появится на странице, лучше всего для этих целей подходит событие DOMContentLoaded у document:
    document.addEventListener('DOMContentLoaded', function() {
      // здесь спокойно можем делать document.querySelector
    });
    Ответ написан
    Комментировать