У меня есть два кода ниже
Отрывок # 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. Это не так.
Пожалуйста, основывайте свои ответы на конвейерной линии, пожалуйста
Я не уверен в причине, но, судя по всему, если вы сначала сохраните offsetWidth
, неважно, насколько вы используете forEach
или map
: вот ручка, чтобы проиллюстрировать это поведение.
Вы можете видеть, что я рассчитал три комбинации:
forEach
с немедленным получением offsetWidth
и width
установкиforEach
с сохранением offsetWidth
и соответствующего элемента сначала, а затем установить ширину в секунду для forEach
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
), чтобы избежать разметки макета. Кажется, проблема в коде тоже.
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
. Просто ищу по этой причине только разницу во времени.
offsetWidth
а затем установка width
сразу же кажется проблемой. Если вы разделили получение и настройку, это намного быстрее. Причина этого, вероятно, связана с внутренними реализациями DOM, а не с кодом JavaScript.
в 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 в этом случае.
Надеюсь, это поможет.
element.style.width = `${element.offsetWidth * 2}px`;
1 на element.style.width = `${element.offsetWidth * 2}px`;
и это все еще намного медленнее codepen.io/anon/pen/yqvOQM?editors=1011
offsetWidth
после изменения свойств CSS приведет к перекомпоновке. Так что прочитайте их все, затем установите все, а не делайте это поочередно. Или вообще не читайте изoffsetWidth
а простоoffsetWidth
значение пикселя, которое было сохранено в.style.width