Pull to refresh
102
0
omfg @omfg

User

Send message
Спасибо за интересный обзор. В свою очередь хотел бы отметить следующее.

В целом «притормаживание скролла» указывает на другую проблему, а именно композиция слоёв (layer compositing). Так как сегодня практически все браузеры используют GPU для отрисовки некоторых вещей, а отовсюду слышится «ставь translateZ(0) чтобы быстро и плавно всё» эта проблема становится очень актуальной.

Если коротко, то в браузерах (как минимум на базе WebKit и Blink) есть набор триггеров, которые переносят некоторые слои на отдельную поверхность на GPU (в терминах Blink это перенос RenderLayer на свой GraphicsLayer). Эти триггеры могут быть как явно указаными у слоя (тот же translateZ(0), CSS-анимации на transform и opacity), так и косвенными, например, не-GPU слой по z-index’у находится выше GPU-слоя и их границы пересекаются.

Вынос на GPU, помимо каких-то внутренних процессов, как правило сопровождается полной перерисовкой слоя, поэтому иногда можно наблюдать всякие «моргания» и прочие артефакты. На GPU такие слои фактически становятся текстурой на плоскости, которой удобно (а самое главное — очень дёшево) можно применять различные 3D-трансформации. Но тут есть один очень важный нюанс: если хотя бы один пиксель текстуры поменяется (например, на ховер, анимацию, что-то ещё) — её нужно заново перерисовать. Это очень сильно заметно, например, в WebKit на iOS. Соответственно, неумелое использование GPU-триггеров для «ускорения» страницы может на самом деле привести к очень серьёзным тормозам.

Из всего вышесказанного конкретно для вашей ситуации: скорее всего, источник проблемы не в самом box-shadow, а в неправильной композиции, которая вызывает неявный вынос на GPU ненужных слоёв и, соответственно, перерисовку тени. Потому что при правильной композиции можно обвешаться различными эффектами и ничего не будет тормозить. Наверняка при включении “Show paint rectangles” вы наблюдали, что область перерисовки занимает всю станицу, хотя по-хорошему так быть не должно.

Дебажить такие вещи очень удобно Safari Web Inspector: там есть отдельная панелька Layers, которая для выделенного элемента показывает, какие слои вынесены на GPU и, что особенно важно, причину такого выноса. Лично я уже нескольким ребятам помог сильно оптимизировать производительность с помощью этого инструмента, особенно для мобилок :)

Чуть подробнее об этом можно почитать тут: www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
Что this во вложенных функциях ссылается на глобальный объект
Не путаемся и других не путаем! Ссылка this зависит от способа вызова функции, а не от способа и места задания функции.

Общее правило запоминания для this (читать как мантру)
1. При прямом вызове функции (т.е. без catch, with, bind, call, apply) то, что слева от точки перед именем функции, то и будет this.
2. Если точки нет this === глобальный объект (для браузеров это window).
3. Если функция стоит в позиции выражения, то this будет всегда глобальный объект

Пример для закрепления:
var c = 0,b,a,e = {c: 8};
a = {
  c: 150,
  b: function() {
    return this.c;
  }
};

// 1. 
a.b(); // 150 this === a смотрим, то что перед точкой

// 2. 
b = a.b;
b(); // 0 this === window ибо точки нет 

// 3. 
(a.b)(); // 150 скибки не ставят функцию в состояние выражения поэтому смотрим то, что перед точкой
(false || a.b)(); // 0 позиция выражение
(0, a.b)(); // 0 позиция выражение
(e.b = a.b)(); // 0 позиция выражение
e.b(); // 8 this === e Если вызвать после присвиавния, то будет работать правило 1
(true ? a.b : a.c)(); // 150 не выражение
a[true ? 'b' : 'c'](); // 150 не выражение

В примере статьи «this во вложенных функциях ссылается на глобальный объект» ситуация номер 2

Information

Rating
Does not participate
Location
Таиланд, Таиланд
Date of birth
Registered
Activity