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

    @GrayHorse
    Функция functionName существует в контексте контент скрипта.

    При добавление кнопки с onclick="functionName()" по клику на нее functionName будет вызывать в контексте веб страницы, где данной функции нет.

    1. Добавь кнопку.
    2. Добавь эвент листенер через addEventListener на нее.

    Будет работать.
    Ответ написан
    1 комментарий
  • Как снести все скрипты на странице?

    @GrayHorse
    Запретить выполнение JS кода (как инлайн, так и загружаемого) можно с помощью Content Security Policy (CSP) заголовков, как это делают NoScript расширения, в частости, uBlock Origin.

    Хотя не уверен, что в таком случае можно выполнить свой код в контексте веб страницы (не в в контексте контент скрипта), хотя, вероятно, можно разрешить сделать это, указав hash/nonce своего кода, в качестве разрешенного к выполнению (опять же — в CSP заголовке).
    Ответ написан
    Комментировать
  • По какой причине скачиваются не все изображения с помощью .click()?

    @GrayHorse
    В Chromium-based браузерах можно успешно скачать по клику на a с аттрибутом download не больше 10 файлов в секунду на вкладку (таб) браузера.
    Ответ написан
    Комментировать
  • Как правильно объединить две js функции в одну?

    @GrayHorse
    Неужели это не лучше?
    async function timer() {
      let countdown = 5;
      while (countdown--) {
        console.log(countdown + 1);
        await sleep(1000);
      };
      console.log("done");
    }
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }


    С отменой на повторном вызове:
    let execId = 0;
    async function timer() {
      let countdown = 5;
      const id = ++execId;
      while (countdown--) {
        if (id !== execId) {
          return;
        }
        console.log(countdown + 1);
        await sleep(1000);
      };
      console.log("done");
    }
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    Ответ написан
  • Как сделать синхронный запрос через fetch?

    @GrayHorse
    Начать использовать оператор await. И не парить мозг.
    Ответ написан
    Комментировать
  • Почему возвращает undefined?

    @GrayHorse
    Промисифицированный аналог:
    function hasBanWords(text) {    
      const url = "banwords.json";
    
      const xhr = new XMLHttpRequest();    
      xhr.open("GET", url);
      xhr.send();
    
      return new Promise(resolve => {
        xhr.addEventListener("load", function() {
            if (this.status === 200) {
              const words = JSON.parse(this.response);
              const hasSomeWords = words.some(word => text.includes(word));
              resolve(hasSomeWords);
            }
        });
      });
    }
    
    console.log(await hasBanWords("bitch on the beach"));
    Ответ написан
    1 комментарий
  • Как отсортировать массив, имеющий текст с числами в JS?

    @GrayHorse
    const {compare} = new Intl.Collator(undefined, {
        numeric: true
    });
    const array = ["x32-Sar", "x2-Far", "x1-Tar", "x11-Har"];
    array.sort(compare); // ["x1-Tar", "x2-Far", "x11-Har", "x32-Sar"]
    Ответ написан
    Комментировать
  • Как можно подключить библиотеку в самом скрипте?

    @GrayHorse
    Дождись загрузки скрипта.

    function appendScript(src, integrity) {
        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.onload = resolve;
            script.onerror = event => reject({message: "Failed to load script", src, integrity, event});
            script.src = src;
            script.async = true;
            if (integrity) {
                script.integrity = integrity;
                script.crossOrigin = "anonymous";
            }
            document.body.append(script);
        });
    }
    Ответ написан
  • Почему цикл выполняется не так, как планировалось?

    @GrayHorse
    Использую постоянно.

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    for (let i = 0; i < 3; i++) {    
        await sleep(1000);
        console.log(i);
    }
    Ответ написан
    Комментировать
  • Могут ли ошибки в консоли Хрома забить оперативную или постоянную память, если да, то как это предотвратить?

    @GrayHorse
    Ничего делать не надо, закрытая консоль хранит лишь последние 1000 записей.
    Ответ написан
    Комментировать
  • Синглтон или обычный объект?

    @GrayHorse
    А что в такой ситуации мешает просто создать объект

    Потому что в Java, C# нельзя написать такое:

    export const singleton = {name: "foo"}; // Полноценный синглтон для JS


    Импортируются и экспортируются лишь классы. Создать глобальную переменную, которая будет хранить глобальное состояние, которую потом можно импортировать в разных файлах (классах) — нельзя.

    Следовательно, нужен класс, у которого будет статическое поле, содержащие это глобальное состояние.

    Т.к. экземпляр класса должен быть только один, кем он должен быть создан? А создается он "автоматически" — непосредственно при загрузке класса в статическом блоке инициализации класса (да, в JS это тоже есть), и в качестве дополнительной меры предосторожности, чтобы никто не создал второй экземпляр, конструктор делается приватным — недоступным для любого кода, который будет работать с этим классом.

    Какие здесь преимущества именно в создании класса?

    Функционально — никакие.
    Код будет выглядеть привычнее для людей знакомых с Java и C#.

    Ради формальности, все-таки да, отличие есть, и оно в том, что в случает использования класса, тот объект будет экземпляром класса синглтон, и еще один экземпляр этого класса создать не получится. Можно даже проверку сделать с помощью instanceof, чтобы удостовериться, что передается именно инстанс того класса, который может быть лишь в одном экземпляре, а не какой-то другой объект. А если это "просто объект" — ты сможешь подсунуть полную "копию" без каких-либо проблем, создав ее с помощью литеральной записи.
    Ответ написан
    Комментировать
  • Как отключить асинхронность в JS?

    @GrayHorse
    Как отключить асинхронность в JS?

    Например, с помощью синхронного XMLHttpRequest, что в приведенном примере кода как раз таки и сделано.
    Всё (весь коллбек на событие клика) выполняется синхронно в рамках одной макро-задачи.

    Т.е., внезапно, наоборот, — чтобы все работало, как задумано, надо включить асинхронность, а, точнее, не выключать ее. Ибо изменения в DOM происходят после завершения макро-задачи.

    Первое изменение DOM (вывод текста загрузки) затирается сразу же изменением DOM, которое выводит данные полученного JSON.

    И первое изменение DOM не может отрендериться, т.к. эвент луп заблокирован синхронным запросом. Оно ждет завершение запроса, а после него уже происходит другое, затирающее изменение.
    Ответ написан
    Комментировать
  • Почему не получается обратиться к this в JavaScript?

    @GrayHorse
    Ошибка в коде в том, что при вызове filter.update.country() this является объект update, а не filter.

    JS код, идентичный коду на Java:
    class Filter {
        static sex = null;
        static player = null;
        static country = null;
    
        static updateSex() {
            Filter.sex = document.querySelector("#sex").value;
        }
        static updatePlayer() {
            Filter.player = document.querySelector("#player").value;
        }
        static updateCountry() {
            Filter.country = document.querySelector("#country").value;
        }
    }
    
    Filter.updatePlayer();
    console.log(Filter.player);

    или
    class Filter {
        constructor() {
            this.sex = null;
            this.player = null;
            this.country = null;
        }
    
        updateSex() {
            this.sex = document.querySelector("#sex").value;
        }
        updatePlayer() {
            this.player = document.querySelector("#player").value;
        }
        updateCountry() {
            this.country = document.querySelector("#country").value;
        }
    }
    
    const filter = new Filter();
    filter.updateCountry();
    console.log(filter.country);


    Ну и рабочий аналог "кода" из вопроса:
    class Filter {
        fields = {
            country: null,
        }
        update = {
            caller: this,
            country() {
                this.caller.fields.country = "123";
            }
        }
    }
    const filter = new Filter();
    filter.update.country();
    console.log(filter.fields.country);
    Ответ написан
    Комментировать
  • Как считывать локальные файлы в контексте расширения для браузера?

    @GrayHorse
    Добавь "unlimitedStorage" в manifest.json
    И храни это в browser.storage.local или в IndexedDB.

    Бонус:
    chrome.storage.local.get(console.log);
    Ответ написан
    1 комментарий
  • Как правильно установить и обработать событие Click?

    @GrayHorse
    currentTarget

    Всегда совпадает с элементом, на котором обработчик события был назначен, в отличие от свойства Event.target, идентифицирующего элемент, на котором событие возникло.
    Ответ написан
  • Почему не работает fetch (JavaScript)?

    @GrayHorse
    в чем проблема?


    Потому что {mode: "no-cors"}.

    Никакой полезной информации из response ты не получишь при кросс-доменных запросах с данным режимом.

    Данный response годится исключительно только для Cache API в Service Worker.
    Ответ написан
    6 комментариев
  • Как сделать выполнение js только на доменах из списка?

    @GrayHorse
    Напиши юзерскрипт вместо расширения.

    Вот пример:
    // ==UserScript==
    // @name        Toster Example
    // @match       https://qna.habr.com/*
    // @match       https://toster.ru/*
    // @grant       GM.xmlHttpRequest
    // @connect     https://example.com
    // ==/UserScript==
    
    !async function() {
        console.log("userscript start");
        const response = await new Promise((resolve, reject) => {
            GM.xmlHttpRequest({
                method: "get",
                url: "https://example.com",
                responseType: "text",
                onload: resolve,
                onerror: reject,
            });
        });
        console.log("response:", response);
    
        const {response: text} = response;
        console.log("text:", text);
    }();


    Запускается на каждой странице Тостера (см @match), и успешно логирует в консоль содержание https://example.com несмотря на CORS.
    Ответ написан
    Комментировать
  • Возможно ли записывать данные в файл на js?

    @GrayHorse
    Можно.

    Если просто сгенерировать на сайте и скачать:

    const blob = new Blob(["The content of the txt file."], {type: "text/plain"});
    const blobUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.download = "filename.txt";
    a.href = blobUrl;
    a.click();
    setTimeout(() => URL.revokeObjectURL(blobUrl), 10_000);


    Если нужно дописать в существующий файл или изменить его содержимое:
    https://web.dev/file-system-access/
    Только его перед этим нужно "открыть". Работает лишь в Chromium браузерах.

    "File System Access API" и "FileSystem API" — не одно и то же.
    Ответ написан
    Комментировать
  • Как перенести объект из JS в другие языки?

    @GrayHorse
    в каком виде CryptoJS принимает в себя инстанс объекта самого себя и что он хеширует, чтобы повторить этот метод используя другие инструменты


    Все криптографические алгоритмы работают с байтами. CryptoJS используется абстракцию в виде класса "WordArray" для представления байтов, т.к. это старая библиотека, написанная, когда не было "ArrayBuffer".

    мне надо чтобы оно НЕ РАБОТАЛО также как и НЕ РАБОТАЕТ в js,

    Оно работает. Причем правильно.

    неужели по Вашему я могу переместиться во времени и пространстве к программисту, который когда-то захешировал слово таким методом и сказать ему "эй, ты хешируешь объект, не надо, хешируй строку" и дать ему этот код?

    На что тот программист бы ответил: "Не неcи чушь".
    И будет прав.

    Т.к. в его случает программа берет байты из строки и хешерует их, потом опять хеширует их же и т.д:
    SHA512(
            SHA512(
                    SHA512("hello".getBytes()) 
            )
    ).toString("hex");

    Для вывода в консоль предстaвляет их в виде хекс строки.

    ---

    Хеши же от вывода якобы той программы на C++:
    SHA512(
            SHA512(
                    SHA512("hello".getBytes()).toString("hex").getBytes()
            ).toString("hex").getBytes()
    ).toString("hex");

    Ничего не смущает? Что здесь cчитается не то же самое.

    ---

    чтобы повторить этот метод используя другие инструменты


    Другие инструменты в виде Java:

    import java.math.BigInteger;
    import java.nio.charset.StandardCharsets;
    import java.security.*;
    
    public class Main {
        public static void main(String[] args) throws NoSuchAlgorithmException {
            byte[] bytesOfMessage = "hello".getBytes(StandardCharsets.UTF_8);
            MessageDigest SHA512 = MessageDigest.getInstance("SHA512");
    
            byte[] digest = SHA512.digest(bytesOfMessage);
            Main.log(digest);
            for (int i = 0; i < 4; i++) {
                digest = SHA512.digest(digest);
                Main.log(digest);
            }
        }
        private static void log(byte[] digest) {
            var hex = new BigInteger(1, digest).toString(16);
            if (hex.length() % 2 == 1) {
                hex = "0" + hex;
            }
            System.out.println(hex);
        }
    }


    Шок! Вывод такой же и у "неправильного" CryptoJS. Банковские приложения в опасносте!

    ---

    Тема — кринж.
    Ответ написан
    1 комментарий
  • Как найти и увидеть данные хранящиеся в chrome.storage(local или sync)?

    @GrayHorse
    В консоли.

    chrome.storage.local.get(console.log);
    chrome.storage.sync.get(console.log);
    Ответ написан