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

    e-vyushin
    @e-vyushin
    Frontend engineer
    Думаю основная причина почему кажется что это должно работать — это непонимание разницы между функцией в JS и методом объекта. Это не одно и то же, несмотря на то что оба варианта можно вызвать подписав скобочки () в конце :) Да, вызывать можно и функцию и метод объекта, а вот создавать экземпляры методов нельзя.

    В указанном Вами примере внутри функции Man вызывается new this.Man. Это означает, что создаётся экземпляр Man, а значит сам Man должен иметь конструктор (грубо говоря быть классом).

    Функции в JS имеют конструктор, а методы объектов не имеют. Функции и методы объектов это не одно и то же. Рассмотрим такой пример:

    const obj = {
       Man() {}
    }

    в данном случае Man() это просто метод объекта. У него нет своего конструктора. Т. е. нельзя создать его экземпляры через new. Но можно его вызвать:

    const obj = {
       Man() {}
    }
    obj.Man();

    это корректный вариант.

    Но создавать экземпляры нельзя. Например:

    const obj = {
       Man() {}
    }
    new obj.Man(); // Будет ошибка. TypeError: obj.Man is not a constructor

    А вот экземпляры функции можно создавать. Например:

    const obj = {
       Man: function() {}
    }
    new obj.Man(); // Всё ок

    для того чтобы создать экземпляр функции не обязательно конечно чтобы она была внутри объекта. Можно и так:

    const Man = function() {}
    new Man(); // Всё ок

    При желании можно поискать инфу на тему почему можно создавать экземпляры функции. Говоря вкратце, раньше в JS не было классов, по-этому наследование было реализовано через прототип функции. Это немного нелепо конечно, но в JS можно создавать экземпляры функции как если бы функция была классом. Сегодня в JS уже есть классы, так что лучше использовать их.

    Вывод: методы объекта и функции это не одно и то же.
    Ответ написан
    1 комментарий
  • Не видит подключенный модуль из node_modules. Почему?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Модули могут не иметь экспорта по-умолчанию. Например, представим, что у нас есть такой модуль:

    // Some module
    const a = 1;
    const b = 2;
    
    export {
      a,
      b
    }

    Такой модуль не имеет экспорта по-умолчанию, соответственно если попытаться его импортировать следующим образом:

    import module from 'module';

    то будет ошибка.

    Чтобы получить экспорт модуля, не имеющего экспорта по-умолчанию, нужно использовать следующую конструкцию:

    import * as module from 'module';
    console.log(module); // {a: 1, b: 2}

    в ответ придёт объект, содержащий в себе все экспорты модуля.

    Получать сразу всё не всегда бывает целесообразно. Чаще требуется получить из модуля что-то конкретное. Сделать это можно следующим образом:

    import { a } from 'module';
    console.log(a); // 1

    также можно импортировать несколько значений, например:

    import { a, b } from 'module';
    console.log(a); // 1
    console.log(b); // 2

    Конкретно в Вашем случае, нужно убедиться, что модуль который Вы пытаетесь импортировать имеет экспорт по-умолчанию. Т. е. нужно посмотреть исходный код модуля, или почитать документацию по нему.

    Больше информации о модулях можно получить по ссылке, рекомендую почитать:
    https://learn.javascript.ru/modules
    Ответ написан
    Комментировать
  • Разделить строку на сегменты примерно по 50 символов?

    e-vyushin
    @e-vyushin
    Frontend engineer
    const str = 'Имеется длинная строка. Мне нужно разделить её на сегменты примерно по 50 символов длинной. Но чтобы слова, находящиеся на границе сегментов не разрывались, а помещались в какой-то один сегмент, это важно. Поэтому сегмент может иметь длинну 41, 45, 49 символов, неважно, главное чтобы не разрывались слова и количество символов в сегменте было примерно 50.';
    str.match(/.{1,50}(\s|$)/mig)


    Рассмотрим подробнее регулярное выражение:

    . — находит любой символ. Под любым символом понимается действительно ЛЮБОЙ символ, на любом языке (латиница, кириллица и т. д.), в т. ч. (внимательно) пробелы и переносы строк.

    {1,50} — количество повторений "любого символа". Указываем, что от 1 до 50 раз.

    (\s|$) — любой пробельный символ или конец строки. Т. е. мы явно указываем, что на конце вхождения должен быть пробел или конец строки. Таким образом мы находим разделения слов. Стоит отметить, что \s также найдёт символ табуляции и переноса строки. Так что, если слова разделаются переносом строк или табом, то это тоже будет учитываться.

    mig — без учёта регистра символов, глобальный поиск по всей строке, поддержка многострочных текстов.

    Результатом данного примера является массив всех вхождений:

    5b8c7c0dd9592795075447.jpeg

    /*======== Поправка от 03.09.2017 20:30 ========*/

    . — находит любой символ кроме перевода строки (\n \r \u2028 or \u2029)

    В связи с этим, более актуальное решение будет выглядеть так:
    const str = 'Имеется длинная строка. Мне нужно разделить её на сегменты примерно по 50 символов длинной. Но чтобы слова, находящиеся на границе сегментов не разрывались, а помещались в какой-то один сегмент, это важно. Поэтому сегмент может иметь длинну 41, 45, 49 символов, неважно, главное чтобы не разрывались слова и количество символов в сегменте было примерно 50.';
    str.match(/(.\n*){1,49}(\s|$)/gi)
    Ответ написан
    3 комментария
  • Как скрыть отправляемые данные при post запросе JS?

    e-vyushin
    @e-vyushin
    Frontend engineer
    То, что находится на стороне клиента - принадлежит пользователю. Сюда относятся токены, идентификаторы, имена, фамилии, e-mail, и т. д. Всё это пользовательские данные.

    Тут действует главное правило. Пользователь видит только то, что Вы ему прислали сами! Если не хотите чтобы он что-то видел, просто не отправляйте ему это. Ни в JS файлах, ни в HTML коде, нигде. Просто не отправляйте и тогда пользователь этого не увидит.

    Вы правы, не все данные принадлежат пользователю. Например, пароли от базы данных, токены которые не связаны с пользователем и т. д. Такие данные хранятся на backend, и не передаются пользователю на клиент.

    В Вашем примере Вы сами прислали пользователю секретный токен, а потом попытались подставить его в POST запрос:

    $.post("test.php", { token: "my_token" } );

    Храните токен на backend.
    Если нужно выполнить какой-либо запрос на сторонный API, то это также можно сделать со стороны backend (в вашем примере из test.php). Backend тоже умеет отправлять POST запросы. Конечно не при помощи jQuery, а при помощи своих инструментов. Вот ими и нужно пользоваться, если речь идёт о необходимости выполнения запросов с секретным токеном.
    Ответ написан
    2 комментария
  • Как определить, что скролить уже некуда?

    e-vyushin
    @e-vyushin
    Frontend engineer
    С помощью jQuery можно так:
    $(window).on('scroll', function() {
        if ($(document).scrollTop() === 0) {
            console.log('Достигнут верхний предел');
        }
    });
    Ответ написан
    Комментировать
  • Как сделать tooltip со скроллом?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Tipped.create('#demo-json', {
              showOn: 'click',
              hideOn: 'click',
              hideOnClickOutside: true,
              padding: false,
              ajax: {
                url: '/js/default/index/brands.json',
                dataType: 'json',
                success: function(data, textStatus, jqXHR) {
                  var brands = data.brands;
    
                  // wrapper for scroll
                  var scrollable = $('<div>').addClass('tooltip-brands tse-scrollable');
    
                  var links;
                  scrollable.append(links = $('<div>').addClass('links tse-content'));
    
                  // container that holds the names
                  $.each(brands, function(i, brand) {
                    var link;
    
                    links.append(link = $('<a>').addClass('close-tooltip')
                      .attr({ href: '#brand-' + brand.id })
                      .append($('<span>').html(brand.name))
                    );
    
                    if (i == brands.length - 1) link.addClass('last');
    
                    // clicking the link shouldn't do anything, just for this demo
                    // we'll make it hide the tooltip
                    link.bind('click', function(event) { event.preventDefault();  });
                  });
    
                  return scrollable;
                }
              },
    
              afterUpdate: function(content) {
                var scrollable = $(content).find('.tse-scrollable');
                scrollable.TrackpadScrollEmulator({ autoHide: false });
              },
    
              onShow: function(content, element) {
                var scrollable = $(content).find('.tse-scrollable');
                scrollable.find('.tse-scroll-content').scrollTop(0);
                scrollable.TrackpadScrollEmulator('recalculate');
              }
            });
    Ответ написан
  • Как лучше разработать логику сайта?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Я прочитал то, что вы написали и сложилось такое впечатление, что вы собираетесь решать админские задачи руками программиста.

    В больших компаниях, к примеру, задачами администрирования серверов и задачами программирования занимаются отдельные люди и решают они поставленные задачи разными инструментами. Вы, как мне показалось, собираетесь решить 2 задачи (администрирование и программирование) одним инструментом — языком программирования и архитектурой кода.

    По этому у вас и возникло сомнение.
    Задачи администрирования серверов и распределение нагрузки — это конечно забота программиста, но не в самой приоритетной степени. В приоритетной степени — это задача администратора серверов.

    Я бы предложил вам писать код так, как будет удобно и правильно с точки зрения архитектуры и дальнейшей поддержки, а задачи нагрузки решить разделением системы на кластеры и распределением нагрузки между ними.
    Ответ написан
  • Можно ли загрузить в iframe страницу и прочитать её JS'ом, чтобы получить секретные данные, доступные только пользователю?

    e-vyushin
    @e-vyushin
    Frontend engineer
    То о чём вы пишете мир уже прошёл.. Следующим этапом был clickjacking. Этот вид атаки позволяЛ выполнять различные действия от имени пользователя.

    Например, известны случаи, когда прозрачный iframe накладывался поверх какой-нибудь кнопки на сайте при нажатии на которую пользователь в действительности кликал не на неё, а на контент во фрейме, за счёт чего выполнялись непреднамеренные действия от имени пользователя.

    В настоящий момент данный вид атаки считается устаревшим.
    На всех популярных сайтах, включая VK, Facebook и т. д., вы можете встретить HTTP заголовок X-Frame-Options со значениями DENY (запрещает открытие во фрейме) или SAMEORIGIN (разрешает открытие во фрейме только в своём домене).
    Собственно, на этом вся история и заканчивается, а идеи хакеров по поводу clickjacking уже не актульны.
    Ответ написан
    5 комментариев
  • Как использовать компоненты ionic?

    e-vyushin
    @e-vyushin
    Frontend engineer
    В документации есть инструкция по установке.
    ionicframework.com/docs/v2/getting-started/installation
    Ответ написан
    3 комментария
  • Как загрузить локальный файл не с веб сервера, а локально?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Если бы локальный файл можно было так легко загрузить через браузер, то при помощи jQuery можно бы было украсть у пользователя все файлы. Браузеры блокируют попытки обращения к локальным файлам стандартными способами.

    Самое быстрое решение, которое могу Вам посоветовать — это установить http-server для node.js и расшарить нужный каталог
    https://www.npmjs.com/package/http-server
    Ответ написан
    Комментировать
  • Текстовый редактор для сайта с плагинами?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Посмотрите в сторону CKEditor
    ckeditor.com
    Ответ написан
    Комментировать