【问题标题】:Is it expensive to read properties from window object?从窗口对象读取属性是否昂贵?
【发布时间】:2019-04-21 00:59:42
【问题描述】:

例如,假设我们有两个版本的延迟加载(参见下面的代码)。在性能方面,第二版是否比第一版更好?

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; 
  }
}

【问题讨论】:

  • 这尖叫着过早的优化。你确定如果一个更快真的很重要吗?
  • 如果可以,请将您的实际代码作为文本编辑到您的问题中 - 代码单独的图像是tedious and difficult,可以使用和调试.它迫使那些本来愿意帮助你的人首先transcribe your image,这是浪费时间。
  • 欣,欢迎来到 Stack Overflow!你的问题很好,我认为,非常重要。我怀疑否决票是因为图像代码,现在已修复。请不要因提问和回答而气馁。 :-)
  • 谢谢迈克尔!你真好~@MichaelCrenshaw

标签: javascript web-performance


【解决方案1】:

您的具体问题:

我将把您的具体问题改写如下:

访问window.innerHeight 和/或window.pageYOffset 成本高吗?

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

以下所有属性或方法,当在 JavaScript 中请求/调用时,都会触发浏览器同步计算样式和布局*。这也称为回流或layout thrashing是常见的性能瓶颈

...

窗口

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

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

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

  • 仅当文档发生更改并导致样式或布局无效时,重排才会产生费用。通常,这是因为 DOM 已更改(修改了类,添加/删除了节点,甚至添加了 :focus 之类的伪类)。
  • 如果强制布局,必须先重新计算样式。所以强制布局会触发这两种操作。 它们的成本在很大程度上取决于内容/情况,但通常这两种操作的成本相似。
  • 您应该如何处理这一切?好吧,下面的更多关于强制布局的部分更详细地介绍了所有内容,但是
    简短版本是:
    1. for 强制布局和更改 DOM 的循环是最糟糕的,避免它们。
    2. 使用 DevTools 时间线查看发生这种情况的位置。您可能会惊讶地看到您的应用程序代码和库代码出现这种情况的频率。
    3. 批量写入和读取 DOM(通过FastDOM 或虚拟 DOM 实现)。在帧开始时读取您的指标(非常开始 rAF、滚动处理程序等),此时数字仍与上次布局完成时相同。

更改src 属性可能足以“使样式或布局无效”。 (虽然我怀疑使用 correctly-dimensioned SVG placeholders for lazy-loaded images 之类的东西会减轻或消除回流的成本。)

简而言之,您的“版本 I”实现更可取,据我所知,没有真正的缺点。

您的一般问题

如上所示,从窗口对象读取属性可能开销很大。但其他人指出几点是对的:

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

【讨论】:

    【解决方案2】:

    这个好像更好

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

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多