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

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    3 принципа ООП - это миф, притом очень вредный.
    Инкапсуляция, наследование и полиморфизм относятся к ООП примерно как кухонный комбайн к варке блюд, их конечно можно использовать вместе, но и друг без друга они живут прекрасно.

    ООП - это про высокоуровневые абстракции представленные в виде объектов, а так же про взаимодействие этих объектов, путем вызова методов. Все. Никаких 3 принципов тут нет. И это примерно одинаково, что в JS, что в C#, что в Java, что в C++, а разница в реализации тут не существенна, Вы о ней знаете, только потому что абстракции текут.

    Инкапсуляция - это сокрытие сложности. Опять же все. Забудьте весь бред про приватные поля и тому подобное. Это не более чем частный случай. И замыкания - это тоже частный случай инкапсуляции. А еще, когда из модуля Вы экспортируете не все подряд (привет ReasonML), а только высокоуровневые штуки, оставляя все остальное недоступным извне. А еще когда некоторое API (REST/GraphQL/RPC/etc.) отгораживает Вас от прямого общения с базой данных - это тоже инкапсуляция.

    Полиморфизм - это возможность некоторой сущности работать с разными типами данных и возможно адаптироваться под них. А еще полиморфизм разный бывает. Помимо полиморфизма подтипов, который чаще всего и приписывают к ООП, бывают и другие. Например очень распространен параметрический полиморфизм, в большинстве языков представленный дженериками. А еще бывает ad-hoc полиморфизм (перегрузки).
    Но даже если рассматривать только полиморфизм подтипов (это когда между типами есть иерархия, то есть отношения подтип-надтип, и мы в переменную/аргумент/поле надтипа можем присвоить значение подтипа), то и тут нет не слова про ООП. Яркий пример - TypeScript, где есть тип unknown, являющийся надтипом любого другого типа и в который можно присвоить значение любого типа, а так же есть тип never, являющийся подтипом любого другого типа и который можно присвоить в любой другой тип.
    Ну и касательно JS, в нем вообще все полиморфно, ибо динамическая типизация.

    Наследование - это вообще частный случай полиморфизма подтипов, отдельно выделяют пожалуй лишь потому, что он не только про типы (как полиморфизм), а еще и про реализации, которые наследуются. И опять же, ничего тут про ООП нет. Наследование вполне может жить и без ООП,
    например во вполне себе структурно-процедурном Си
    #include <stdio.h>
    
    struct Parent
    {
        int a;
        int b;
    };
    
    struct Child
    {
        struct Parent __super;
        int c;
    };
    
    void f(struct Parent* v)
    {
        printf("a: %d\nb: %d\n", v->a, v->b);
    }
    
    int main()
    {
        struct Child v = {{10, 20}, 30};
        f((struct Parent*)&v);
        printf("c: %d\n", v.c);
        return 0;
    }


    P.S. JS вполне себе компилируемый язык, у v8 даже ассемблерный код попросить можно, который он накомпилит с Вашего JS.
    Ответ написан
    1 комментарий
  • Как вызвать функцию из прототипа (рекурсия)?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://developer.mozilla.org/ru/docs/Web/JavaScri...
    https://developer.mozilla.org/ru/docs/Web/JavaScri...

    А вообще, мутировать прототип не своих сущностей, а особенно глобальных - очень плохо, в лучшем случае Вас побьют, в худшем...
    И главное зачем? Есть https://developer.mozilla.org/ru/docs/Web/JavaScri...

    Ну и еще, у рекурсии есть ограничение на размер call stack, если это тестовое, то я бы обязательно вставил в проверку такой массивчик:
    let arr = [1];
    for (let i = 0; i < 65536; i++) arr = [arr];
    Ответ написан
    Комментировать
  • Не могу понять как это сделать?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В браузере нет require
    Этот код или под нодой должен запускаться или собираться с помощью webpack
    Ответ написан
    Комментировать
  • Как посчитать количество функций в коде JS?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Такие задачи однозначно решаются обходом AST. Возьмите общеизвестный парсер и инструмент для обхода его дерева, например связка из @babel/parser и @babel/traverse подойдет.
    Так же можно посмотреть в какие ноды что парсится с помощью https://astexplorer.net/ - в нем несколько языков, а для js/ts на выбор есть несколько парсеров.
    Вам по сути нужно найти FunctionDeclaration содержащий в body ReturnStatement и извлечь из него Identifier соответствующий имени. А для второй части - FunctionDeclaration с ArgumentsList не нулевой длины.
    Ну и так как в условии сказано, что внутрь не заходить, то можно пройтись лишь по верхнему уровню, тогда @babel/traverse и не нужен даже
    Ответ написан
    3 комментария
  • Как написать регулярку на допуск только цифр и точек?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Выбирайте, что больше нравится:
    /^(\d|\.)*$/
    /^[.0-9]*$/
    /^[\d.]*$/


    Но я бы все же ограничил одной точкой:/^\d*\.?\d*$/
    Ответ написан
    3 комментария
  • Можно ли несколько раз проксировать объект?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если свойства заранее известны, то проще get/set сделать.
    А Proxy перехватывает все поля без исключения. Можно разве не все хандлеры определять, вместо пропущенных будут использоваться одноименный функции из Reflect, что по сути приведет к поведению как у оригинального объекта.
    Ну и да, на один объект можно повесить любое число Proxy и о них не узнает ни оригинальный объект ни другие прокси.
    Ответ написан
    Комментировать
  • Как происходит всплытие переменной?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Объявления переменных и функций всплывают на верх области видимости, у var и function (та что declaration) - это внешняя функция или модуль (если на верхнем уровне дело происходит), у let и const - блок, то есть после всплытия, внутри движка Ваш код будет выглядеть так:
    var foo; 
    function bar() {
        var foo; // эта foo перекрывает foo из внешней области видимости, и поэтому в функции используется она
        if (!foo) { 
            foo = 10; 
        } 
        console.log(foo); 
    }
    foo = 1;
    bar(); //--> 10


    Так же важно знать, что хотя let и const всплывают наверх блока, но использовать их до фактического места объявления нельзя, так будет ошибка:
    {
        console.log(x); // ReferenceError: Cannot access 'x' before initialization
        let x;
    }
    Это механизм защиты "от дурака" и называется он "мертвое всплытие". По этому всегда лучше использовать let или const, притом const предпочтительнее если переменная не меняется, так как дает больше гарантий.
    Ответ написан
    2 комментария
  • В чем превосходство Typescript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Как бы это странно не звучало, но одно из главных преимуществ TypeScript - это ускорение разработки в несколько раз. Да, когда еще ничего нет - разработка незначительно замедлится, так как помимо логики нужно описать еще и типы. Но это только в начале. И это не только возможность писать большую часть кода с помощью автодополнения. Поддержка существующего кода занимает в десятки раз больше времени, чем его начальное написание. Стоит ли вложить несколько лишних часов на старте, чтоб сэкономить в последствии месяцы? Как по мне стоит.

    Еще одним огромным плюсом является возможность проектировать на типах. Познав дзен TypeScript'а я перестал пользоваться UML, так как типы дают мне ту же наглядность, но при этом еще и сокращают время, так как типы - это уже код. Ну и источник правды остается один. Бизнес требования выраженные в типах не дают отклонится от них при написании логики, исключая возможность неправильной трактовки задачи. Перенеся задачу в типы, я могу обсудить ее с коллегами и исправить неточности еще до написания кода, что опять же сильно экономит время.

    Ну и отвчечу на некоторые Ваши сомнения:
    TSLint в VSCode прям жутко тугой
    TSLint официально deprecated, вместо него стоит использовать плагин к eslint, заодно можете мой конфиг попробовать.

    Типы? Есть JSDOC
    JSDoc в плане типов не умеет и 10% того, что умеет TypeScript. Кроме того, никто в здравом уме не пишет JSDoc на приватную логику, а значит проверки типов там не будет. JSDoc не гарантирует корректность рефакторинга, а вот благодаря TypeScript я, опять таки, точно не забуду обновить JSDoc.

    многие библиотеки nodejs не имеют типов
    может лет 5 назад так и было, но сейчас встретить библиотеку без типов - скорее исключение. Если библиотека популярная, но не предоставляет типов, скорее всего их уже написал кто-то другой, достаточно просто установить одноименный модуль из npm скоупа types и все будет работать само.

    Поддержка браузерами скомпилированного кода? Да какбы почти весь JS имеет поддержку 95%+, тот же Babel уже забыл когда использовал.
    Вообще это не основная задача компилятора TypeScript, а опциональная возможность. И babel + preset-env с ней справляются гораздо лучше. И никто не мешает использовать их вместе. А еще думаю вопрос времени, когда кто-то напишет оптимизатор кода использующий информацию о типах из TS.

    Примерно в каждой второй есть инстансы, на которые смотришь - и чешешь репу - а как называется тип этой переменной в @types/?
    import {someObject} from 'some-library';
    
    type TypeFromValue = typeof someObject;
    const valueCopy: TypeFromValue = {
        ...someObject,
        type: 'overrides',
        with: 'type check',
    };
    и кстати, вот пример того что JSDoc типы не умеют.

    //@ts-check
    и почти везде останется бесполезный any.

    P.S. удачи такие типы на JSDoc описывать
    P.P.S. Еще прелести современного TypeScript невозможные у...
    Ответ написан
    8 комментариев
  • Почему нет разницы в производительности между fork mode и cluster mode в PM2?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Во-первых, cluster мод отличается от fork только тем, что умеет шарить слушаемые tcp порты между процессами. И там и там процессов будет ровно столько, сколько настроите, а значение по умолчанию - количество физических потоков (логических ядер) системы.
    Во-вторых, "двухядерный сервак с 2Гб оперативой" выглядит как виртуалка на большом сервере, где Вам выделили некоторые ресурсы. И ваши 2 ядра вполне могут быть логическими, но физически - 1 ядром или даже его половиной (если 4 потока на ядро), за счет гипертрединга. Вот только гипертрединг штука нацеленная на лучшую утилизацию ресурсов процессора при простоях, а вот при большой нагрузке он вполне себе может замедлить систему, особенно основанную на кооперативной многозадачности (асинхронном исполнении) как в ноде.
    Ответ написан
    1 комментарий
  • Как сделать чтобы отрабатывало событие зажатой ЛКМ и движения мыши?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вы функцию playAudio отдаете как event listener, в нее придет единственный аргумент - объект события, откуда должен взяться data - вообще не понятно.

    Ну и вот так работать не будет:
    piano.addEventListener("mousedown", startKeyActive, playAudio);
    Ответ написан
  • Как менять динамически имя переменной?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    locations[`coord_${count}`]
    это же базовый синтаксис языка...
    Ответ написан
    Комментировать
  • Как седлать рандом с примером ниже толь с шансом на выпадение какого либо варианта (JavaScript Jquery)?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    console.log(getRandomVariant([
        {chance: 0.4, value: 'Текст1'},
        {chance: 0.2, value: 'Текст2'},
        {chance: 0.15, value: 'Текст3'},
        {chance: 0.25, value: 'Текст4'},
    ]));
    
    function getRandomVariant(variants) {
        const sortedVariants = getRandomVariant.cache.get(variants) ?? getRandomVariant.cache
              .set(variants, variants.slice().sort((a, b) => b.chance - a.chance))
              .get(variants);
        let rand = Math.random();
        for (const {chance, value} of sortedVariants) {
            if (chance > rand) return value;
            rand -= chance;
        }
    }
    getRandomVariant.cache = new WeakMap();
    Ответ написан
    Комментировать
  • Как посчитать среднее значение данных в массиве?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const averages = Array.from(
        arr
            .flatMap(v => v.properties.groups)
            .reduce((acc, {id, 'well-being': value}) => {
                const [count, total] = acc.get(id) ?? [0, 0];
                acc.set(id, [count + 1, total + value]);
                return acc;
            }, new Map())
            .entries(),
        ([id, [count, total]]) => ({id, average: total / count}),
    );
    console.log(averages);
    Ответ написан
    Комментировать
  • Как правильно сделать Прогрессбар под %?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const limit = (min, max) => value => Math.min(max, Math.max(min, value));
    const progressLimit = limit(0, 100);
    
    $('#xp').text(this.xp + '%').css({width: progressLimit(this.xp) + '%'});
    Ответ написан
    3 комментария
  • Хочу узнать мнение программистов о моем первом проекте?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если бы мне показали такой проект в качестве портфолио, у меня бы сразу возникло несколько вопросов:
    1) Зачем препроцессоры (sass и pug) в проекте если Вы не используете их возможности? Только ради другого синтаксиса?
    2) Зачем в репозитории лежит вендорный код, особенно сжатый?
    3) Почему в проекте нет линтера (например eslint) и как следствие нет единого стиля кода?
    4) в git один единственный коммит? Вы правда все это выдали на одном дыхании?
    5) Что делает эта регулярка? И почему именно эти символы вводить нельзя, а например 非常糟糕的符号 вполне можно?
    Ответ написан
    4 комментария
  • Почему возвращается пустой массив?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Изучите внимательно метод splice, обратите внимание, что он принимает, что возвращает и какие побочные эффекты оказывает на массив, на котором применяется
    Ответ написан
    Комментировать
  • Какая разница между await и Promise?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    (async () => {
      const result = await {
        then(resolve) {
          console.log('Привет сахар');
          setTimeout(() => resolve(10), 3000);
        }
      };
      console.log('Ух ты, данные из таймера:', result);
    })();

    (async () => {
      try {
        await {
          then(_, reject) {
            console.log('Привет сахар');
            reject(new Error('Ошибочка'));
          }
        };
        console.log('Это никогда не выполнится');
      } catch (e) {
        console.log('Ух ты, эксепшн:', e);
      }
    })();

    console.log('Промисы никуда не делись?', (async () => {})() instanceof Promise)
    Ответ написан
    Комментировать
  • Как получить названия функций из объекта, который является результатом выполнения функции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Не совсем понятен вопрос, но догадываюсь, что нужна правильная типизация данного хука, IDE именно на нее смотрят для формирования списка автокомплита.
    Можно сделать примерно так: https://www.typescriptlang.org/play?#code/C4TwDgpg...
    Ответ написан
    Комментировать