Проверка ширины и установка ширины внутри цикла forEach

1

У меня есть два кода ниже

Отрывок # 1

const doubleWidth = (element) => {
  const width = element.offsetWidth;
  element.style.width = '${width * 2}px';
};
button.addEventListener('click', (event) => {
  boxes.forEach(doubleWidth);
});

Отрывок # 2

button.addEventListener('click', (event) => {
  var widths = boxes.map(item => item.offsetWidth);
  boxes.forEach((element, index) => {
         element.style.width = '${widths[index] * 2}px';
  });
});

У фрагмента № 1 есть много 48 мс по сравнению с фрагментом № 2, который составляет всего 18,4 мс. Почему это поведение?

В конце концов, я все еще выполняю две операции расчета и настройки (которые перерабатывает forcers).

Здесь полный код - https://codepen.io/kushalmahajan/pen/mjXVqp?editors=0010

Обновление. Итак, позвольте мне объяснить немного больше

В Snippet # 1 я каждый раз вижу такой шаблон, как вычисление, сброс, вычисление, сброс... так далее

В фрагменте № 2. Это не так.

Пожалуйста, основывайте свои ответы на конвейерной линии, пожалуйста

  • 0
    Интересно, похоже, что разница заключается в доступе к элементу DOM при чтении и записи (протестировано с Chrome)
  • 0
    Чтение offsetWidth после изменения свойств CSS приведет к перекомпоновке. Так что прочитайте их все, затем установите все, а не делайте это поочередно. Или вообще не читайте из offsetWidth а просто offsetWidth значение пикселя, которое было сохранено в .style.width
Теги:
performance
performance-testing

2 ответа

0

Я не уверен в причине, но, судя по всему, если вы сначала сохраните offsetWidth, неважно, насколько вы используете forEach или map: вот ручка, чтобы проиллюстрировать это поведение.

Вы можете видеть, что я рассчитал три комбинации:

  1. forEach с немедленным получением offsetWidth и width установки
  2. forEach с сохранением offsetWidth и соответствующего элемента сначала, а затем установить ширину в секунду для forEach
  3. map с сохранением offsetWidth и затем установив width элементов в цикле forEach

Вариант 2. 3. были в основном одинаковыми. Судя по этому, я бы сказал, что комбинация получения offsetWidth и установочной width является узким местом производительности. Не могу сказать вам гораздо больше, извините!


window.onload = () => {
    const boxes = Array.from(document.querySelectorAll('.box'));

    document.getElementById('double-sizes-forEach')
    .addEventListener('click', (event) => {
        console.time('Double Sizes ForEach');

        boxes.forEach((element, index) => {
        const width = element.offsetWidth;
        element.style.width = '${width * 2}px';
        });

        console.timeEnd('Double Sizes ForEach');
    });

    document.getElementById('double-sizes-forEach-2')
    .addEventListener('click', (event) => {
        console.time('Double Sizes ForEach 2');

        let a = [];
        boxes.forEach((element, index) => {
        a.push([element, element.offsetWidth]);
        });
        a.forEach(([e, w]) => {
        e.style.width = '${w * 2}px'; 
        });

        console.timeEnd('Double Sizes ForEach 2');
    });

    document.getElementById('double-sizes-map')
    .addEventListener('click', (event) => {
        console.time('Double Sizes Map');

        var widths = boxes.map(item => item.offsetWidth);
        boxes.forEach((element, index) => {
            element.style.width = '${widths[index] * 2}px';
        });

        console.timeEnd('Double Sizes Map');
    });
};

ВЫХОД:

Double Sizes ForEach: 12.341064453125ms
Double Sizes ForEach 2: 0.539794921875ms
Double Sizes Map: 0.590087890625ms

ЗАМЕТКИ:

Во второй статье утверждается, что вы всегда должны отделять изменяющийся стиль (например, width установки) и принимать измерения (например, получать offsetWidth), чтобы избежать разметки макета. Кажется, проблема в коде тоже.

  • 0
    I'm not sure about the reason, but apparently if you store offsetWidth first, it doesn't matter performance-wise whether you use forEach or map . О нет. Я не указываю оружие на forLoop или map . Просто ищу по этой причине только разницу во времени.
  • 0
    @kushalvm я вижу! В любом случае, кажется, что получение offsetWidth а затем установка width сразу же кажется проблемой. Если вы разделили получение и настройку, это намного быстрее. Причина этого, вероятно, связана с внутренними реализациями DOM, а не с кодом JavaScript.
Показать ещё 3 комментария
0

в Snippet 1 каждый раз, когда вы выполняете 2 команды:

const width = element.offsetWidth;
element.style.width = '${width * 2}px';

в то время как в Snippet 2 каждый раз, когда вы выполняете только 1 команду:

element.style.width = '${widths[index] * 2}px';

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

const width = element.offsetWidth;

Для справедливого сравнения двух фрагментов я бы предложил удалить указанную выше команду из цикла и проверить, сколько времени потребуется для выполнения фрагмента 1 в этом случае.

Надеюсь, это поможет.

  • 0
    Я изменил фрагмент element.style.width = `${element.offsetWidth * 2}px`; 1 на element.style.width = `${element.offsetWidth * 2}px`; и это все еще намного медленнее codepen.io/anon/pen/yqvOQM?editors=1011
  • 0
    Я думаю, что это вычисление переменной: doubleWidth, которая вычисляется и сбрасывается каждый раз, и поэтому она не отображается во фрагменте 2, этот расчет и сброс могут также занимать много времени.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню