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

    Alexandroppolus
    @Alexandroppolus
    кодир
    Потому что во время вызова конструктора ClassA, где у тебя вызывается init из ClassC, объект ещё "не доделан", где-то внутри, до полноценного экземпляра ClassC, в частности, ему ещё не добавлены приватные методы ClassC.

    Скопируй в консоль Хрома этот код:
    код

    class ClassA {
        constructor(){
            this.#methidA();
            this.init();
        }
        
        init(){
        
        }
    
        #methidA(){
            console.log('in ClassA.#methodA');
        }
    }
    
    class ClassC extends ClassA {
        init(){
            console.log('*** this in init(): ', this);
            debugger;
        }
        
        #methidC(){
            console.log('in ClassC.#methodC');
        }
        callMethidC() {
            console.log('*** this in callMethidC(): ', this);
            debugger;
            this.#methidC();
        }
    }
    
    const c = new ClassC();
    c.callMethidC();



    и нажми ентер.

    на брекпоинтах разверни в консоли экземпляр класса, который будет в последних выводах в консоль (это надо делать именно во время остановок на брекпоинтах, иначе будет одинаково).
    можно увидеть, что в первом случае в [[PrivateMethods]] не хватает метода #methidC()

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

    надо поисследовать, почитать спецификацию. Сам их не использую, у нас на работе TS )
    Ответ написан
    2 комментария
  • Как интерпретировать дополнительную вложенность прототипа?

    Alexandroppolus
    @Alexandroppolus
    кодир
    obj.__proto__.__proto__ равен null, всё в порядке)

    скорее всего, так показывает браузерная консоль.
    [[Prototype]] - то что лежит в прототипе.
    Но в самом "дальнем" прототипе (который равен Object.prototype) нашлось свойство __proto__, (не поле, а свойство) которое при раскрытии вычисляется для самого объекта obj, и возвращает его прототип.

    сделай obj.__proto__ = {b:2} , снова посмотри obj в консоли, и тебе станет понятен этот мой пятничный поток сознания
    Ответ написан
  • Можно ли задать направление изменения цвета?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Попробуй анимировать background: linear-gradient
    Ответ написан
    2 комментария
  • Почему я больше не получаю The operation is insecure?

    Alexandroppolus
    @Alexandroppolus
    кодир
    По ссылке упоминается строка image.crossOrigin = "anonymous"; Вот это оно самое.

    Если бэк добавляет в картинку заголовок ответа "Access-Control-Allow-Origin: *", то всё будет норм, с канвы можно забирать toDataURL и т.п. Иначе картинка с таким атрибутом просто не загрузится.
    Ответ написан
  • Почему константа const позволяет изменять значение внутри себя не по ссылке?

    Alexandroppolus
    @Alexandroppolus
    кодир
    для const по сюжету задана "блочная область видимости". Т.е. на каждой итерации создается новая константа, по завершении итерации уничтожается
    Ответ написан
    1 комментарий
  • Как дождаться загрузки всех данных через Promise.all() и отрендерить их?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Этот твой getDetails возвращает промис, который резолвится массивом промисов. Оный массив не thenable, потому "окончательно резолвится" сразу. Соответственно, Promise.all, получая на вход массив завершенных промисов, тоже не будет чего-то ждать и вернет завершенный промис, значением которого будет массив массивов промисов (находящихся в состоянии загрузки). И только внутри renderDetailsPage2 начинается "поштучная" работа с промисами загрузки и её реальное ожидание.

    Переделать надо примерно так:
    export function getDetails(apiUrl) {
      return Promise.all(apiUrl.map(url => fetch(url).then(res => res.json())));
    }
    
    export function renderDetailsPage2(dataDetails, filmList) {
      return dataDetails.forEach(detail => {
          const filmItem = document.createElement('li');
          filmItem.classList.add('list-group-item', 'd-flex', 'flex-column');
          filmItem.textContent = detail.name;
    
          filmList.append(filmItem);
      })
    }

    Теперь getDetails возвращает промис, который резолвится не массивом промисов, а массивом результатов загрузки (т.е. не сразу, а когда все будут загружены).
    Promise.all в функции render ждет резолва всех троих, и теперь уже значением его промиса будет массив массивов результатов. Посему в renderDetailsPage2 уже не надо ждать никакого резолва, там в dataDetails - готовый массив значений.

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

    Alexandroppolus
    @Alexandroppolus
    кодир
    https://developer.mozilla.org/ru/docs/Web/JavaScri...

    если не хочешь создавать новый массив, то пройди forEach , в каждой итерации console.log если элемент подходящий
    Ответ написан
    Комментировать
  • Что делать, если много условностей? ?? :: :, и как правильно его читать? Можно ли ссылку на статью какую нибудь?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Вложенные тернарники легко читаются, только если они "линейные". То есть когда в выражении C ? A : B выражение А не содержит в себе тернарник.

    Твой пример можно переписать так:
    !isError ? 'noTab' :
        this.isEmpty(formData.error.decision.result) ? 'noTab' :
        !formData.error.decision.result ? 'noTab' :
        'errorTab' ;


    я просто инвертировал все условия. И теперь тернарник читается строго по порядку: если первое условие истинно, вернуть первое значение и не смотреть дельше. Если второе условие истинно, вернуть второе значение и не смотреть дельше. И т.д. Аналог "быстрого выхода", как в https://qna.habr.com/q/1289362
    Сравни это с исходным вариантом, где самое последнее значение относилось к первому условию, хотя отстояло от него на километр.
    Ответ написан
    Комментировать
  • Какой правильный порядок будет в консоли?

    Alexandroppolus
    @Alexandroppolus
    кодир
    почему дальше у нас сначала идет лог из рефа ребенка, а только потом из рефа родителя - непонятно

    назначение рефов происходит на том же этапе, что и выполнение колбэка в useLayoutEffect: синхронно сразу после того, как сформируется дерево виртуального дома, и по нему будет обновлено дерево реального дома. Все перечисленное делается в одном синхронном куске кода, без микротасков и т.д. Разумеется, до этапа отрисовки на экране.
    Почему снизу вверх, то есть от чилдов к парентам? Значения рефов могут использоваться в колбэках useLayoutEffect, значит они к этому моменту должны быть готовы. Т.е. чилд должен успеть назначить реф до того, как парент попробует к нему обратиться. Распространение данных в обратную сторону, в комплект к распространению в прямую (через пропсы). Это одна из причин, могут быть и другие.

    Эффекты useEffect срабатывают после отрисовки на экране, т.е. в отдельном таске. Для единообразия они тоже срабатывают в порядке от чилдов к парентам.

    Указанный порядок имеет свои минусы, например https://habr.com/ru/articles/574536/ , но в целом плюсы перевешивают.

    Надо заметить, что и функции очистки для useEffect и useLayoutEffect тоже вызываются сначала на чилдах, что правильно со всех сторон.
    Ответ написан
    Комментировать
  • Как избежать дублирования повторяющихся свойств и значений в объектах массива?

    Alexandroppolus
    @Alexandroppolus
    кодир
    эту странную хотелку можно сделать через прототипы
    const commonData = {
        title: "Title",
        description: "Description",
    };
    
    const arr = [
        {value: 'Value1'},
        {value: 'Value2'}
    ].map((obj) => Object.setPrototypeOf(obj, commonData));
    
    console.log(arr[0].value); // Value1
    console.log(arr[0].title); // Title


    но если твой массив пришел с бэка и был распарсен, то уже нет смысла мутить
    Ответ написан
  • Почему из-за Suspense в React.js(ts) не срабатывает onLoadedData на видео?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Самое странное то, что на продакшн версии обработчик корректно работает

    почти наверняка из-за React.StrictMode - там двойное монтирование, и вообще всё двойное. Попробуй его убрать.
    Ответ написан
    3 комментария
  • Как Map запоминает адрес ключа, который является объектом?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Как в Map запомнился этот ключ в виде объекта

    В js объект представлен ссылкой на объект, т.е. (под капотом) указателем на некоторый участок в памяти. Этот указатель - просто некоторое целое число, которое мы посмотреть не можем, но Map может. Те есть ключ по факту является числовым значением, а не каким-то непонятным "объектом".

    как я могу обратится к Map через Map.get, чтобы получить значение ключа, который был объектом в переменной obj, но после я переменную перезаписал?

    Пройтись по всем ключам, среди них будет твой потерянный. Напрямую через Map.get никак.
    Ответ написан
    Комментировать
  • Дублирует ли DataTransfer файлы помещенные в него?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Я не заглядывал в исходники, но кажется, нет ни одной причины дублировать файлы или блобы, они ведь иммутабельны
    Ответ написан
    Комментировать
  • Ошибка в React.js "The `style` prop expects a mapping from style properties to values, not a string..?

    Alexandroppolus
    @Alexandroppolus
    кодир
    В проп style надо передавать объект, а ты зачем-то ставишь туда строку.
    Ответ написан
    Комментировать
  • Существует ли в JavaScript, какая-либо возможность получить содержимое метода в виде строки?

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

    Alexandroppolus
    @Alexandroppolus
    кодир
    Куда копать?

    в сторону console.log, как и всегда. Обвешивай код логами и смотри, что вызвалось а что нет.

    из наиболее частых кейсов - скрипт ищет (например, через querySelector) какой-нибудь элемент, который ещё не успел создаться и потому не нашелся. Тут обычно делается несколько попыток его найти через интервалы времени.
    Ответ написан
    7 комментариев
  • Почему функция возвращает undefined?

    Alexandroppolus
    @Alexandroppolus
    кодир
    твоя задача - хороший пример, где не надо в рекурсию. Можно легко переписать на цикл:

    const removeParenthesesNR=(s)=>{
        let len = -1;
        while(len !== s.length) {
            len = s.length;
            s = s.replace(/\([^()]*\)/g, "");
        }
        return s;
    }


    но даже в этом варианте очень медленно работает на строках с большой глубиной вложенности скобок.

    вот, более быстрый способ:
    function removeParentheses(str) {
        const arr = [];
        let idx = 0, depth;
        while (idx < str.length) {
            const newIdx = str.indexOf('(', idx);
            if (newIdx < 0) {
                break;
            }
            arr.push(str.substring(idx, newIdx));
            
            for (depth = 1, idx = newIdx + 1; idx < str.length && depth; ++idx) {
                const c = str[idx];
                depth = depth + (c === ')' ? -1 : c === '(' ? 1 : 0);
            }
        }
        return arr.join('') + str.substr(idx);
    }


    если сравнивать на строках вида "(((((...)))))", то для глубины 100000 разница в скорости просто гигантская
    Ответ написан
    Комментировать
  • Почему возникает ошибка с if?

    Alexandroppolus
    @Alexandroppolus
    кодир
    на скриншоте видно, что entryChildrenChildren[i][j] могут быть как элементами, так и текстовыми нодами. У последних нет hasAttribute.

    перед вызовом hasAttribute проверяй наличие этой функции у объекта entryChildrenChildren[i][j]
    Ответ написан
    3 комментария
  • Почему способ объявления переменной i влияет на результат?

    Alexandroppolus
    @Alexandroppolus
    кодир
    И еще вопрос: ждет ли тело функции выполнение setTimeout?

    нет.

    чтобы цикл ждал на каждой итерации, надо промисифицировать setTimeout, цикл запускать в async-функции, таймер авайтить.

    const delay = (ms) => new Promise(r => setTimeout(r, ms));
    
    async function run() {
        for (var i = 0; i < 3; i++) {
            await delay(1000);
            console.log(i);
        }
    }
    
    run();


    и теперь уже без разницы, let или var, думаю понятно почему.
    Ответ написан
    Комментировать