从 window 对象读取属性是否昂贵?

Is it expensive to read properties from window object?

例如,假设我们有两个版本的 lazyload(见下面的代码)。在性能方面,版本二比版本一好吗?

const imgs = document.querySelectorAll('img'); 
window.addEventListener('scroll' , lazyload);

// version I 
function lazyload() { 
  imgs.forEach((img) => { 
    if (img.offsetTop < window.innerHeight + window.pageYOffset) { 
      img.src = img.dataset.src; 
    }
  }
}

// version II
function lazyload() { 
  const innerHeight = window.innerHeight; 
  const pageYOffset = window.pageYOffset; 
  imgs.forEach((img) => { 
    if (img.offsetTop < innerHeight + pageYOffset) { 
    img.src = img.dataset.src; 
  }
}

这个看起来更好

// version III
function lazyload(){
  const dimension = window.innerHeight + window.pageYOffset;
  img.array.forEach(img => {
    if (img.offsetTop < dimension) {
      img.src = img.dataset.src;
    }
  });
}

您的具体问题:

我会像这样改写你的特定问题:

Is it costly to access window.innerHeight and/or window.pageYOffset?

可以。根据Paul Irish of the Google Chrome Developer Tooling team:

All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.

...

window

window
window.scrollX, window.scrollY
window.innerHeight, window.innerWidth
window.getMatchedCSSRules() only forces style

-- What forces layout / reflow(强调我的)

bottom of that document,Paul 指出布局回流只会在某些情况下发生。下面的部分(我特别强调)比我能更好、更权威地回答你的问题。

  • Reflow only has a cost if the document has changed and invalidated the style or layout. Typically, this is because the DOM was changed (classes modified, nodes added/removed, even adding a psuedo-class like :focus).
  • If layout is forced, style must be recalculated first. So forced layout triggers both operations. Their costs are very dependent on the content/situation, but typically both operations are similar in cost.
  • What should you do about all this? Well, the More on forced layout section below covers everything in more detail, but the
    short version is:
    1. for loops that force layout & change the DOM are the worst, avoid them.
    2. Use DevTools Timeline to see where this happens. You may be surprised to see how often your app code and library code hits this.
    3. Batch your writes & reads to the DOM (via FastDOM or a virtual DOM implementation). Read your metrics at the begininng of the frame (very very start of rAF, scroll handler, etc), when the numbers are still identical to the last time layout was done.

更改 src 属性可能足以 "invalidate the style or layout."(尽管我怀疑使用 correctly-dimensioned SVG placeholders for lazy-loaded images 之类的东西会减轻或消除回流成本。)

简而言之,您的 "version I" 实施更可取,据我所知,没有真正的缺点。

你的一般问题

如上所示,从 window 对象 读取属性可能 开销很大。但其他人指出几件事是正确的:

  1. 过早或过于积极地优化会浪费您宝贵的时间、精力和(取决于您的解决方案)可维护性。
  2. 唯一确定的方法就是测试。尝试两个版本的代码,并仔细分析您最喜欢的开发工具的输出以了解性能差异。