【问题标题】:Which is better for performance, elements in DOM or in Javascript object?DOM 中的元素还是 Javascript 对象中的元素哪个更利于性能?
【发布时间】:2016-01-08 04:43:20
【问题描述】:

就性能而言,在 DOM 树中包含 20 个元素(及其子元素)更好还是将所有内容存储在 Javascript 对象中?

案例一:

<html>
    <body>
        <div id='el1'>
            <span>...</span>
            ...
        </div>
        <div id='el2'>            
            <p>...</p>
            ...
        </div>
        <div id='el3'>            
            <img src="" alt="" />
            <br/>
        </div>
        <div id='el4'>
            <section></section>
            ...
        </div>
        ...
    </body>
</html>

案例 2:

var OBJ = {};
OBJ.el1 = $("<div id='el1'><span>...</span>...</div>");
OBJ.el2 = $("<div id='el1'><p>...</p>...</div>");
OBJ.el3 = $("<div id='el1'><img src="" alt="" /><br/>...</div>");
OBJ.el4 = $("<div id='el1'><section></section>...</div>");
....

我的应用程序一次应该只显示这些元素之一。如果我只是将它们留在 DOM 树中并更改它们的样式,它会表现得更好,还是最好将它们存储在 Javascript 对象中并在需要时删除并附加它们?

我该如何测试它?

@编辑 需要考虑的额外信息:

1- 所有元素都写入 HTML 文档,然后在页面加载时将其删除并存储在 javascript 对象中。

2- 每次活动元素更改时,我都会通过删除当前活动元素然后将新元素附加到它来更改 DOM 结构。

@EDIT 2:经过一些测试

这个想法是:有人将 HTML 元素写入 DOM,然后 Javascript 必须一次只显示/隐藏其中一个元素。这些元素有自己的孩子。它可以是整页网站或 Web 应用程序。

我创建了 2 个测试用例:

1- 元素将被移除,然后被 Javascript 多次重新附加。所以它们将被存储在一个 Javascript 对象中,直到它被召唤

2- 元素将在 DOM 中,我将在需要时隐藏和显示它们(jQuery 函数,但进一步的测试将直接更改 CSS)。

<html>
<head>
    <script src='https://code.jquery.com/jquery-1.11.3.min.js'></script>
</head>
<body>
    <!-- I USED 15 ELEMENTS IN MY TEST, BUT THE CODE IS TOO LONG -->
    <script>
    var OBJ1 = {};
    var OBJ2 = new Array();
    var ACTIVE;
    var BODY = $(document.body);
    var T1, T2, DELTA;

    $(function(){
        T1 = new Date().getTime();
        /*
        //TEST 1: Javascript
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ1[id] = _this;
            _this.remove();
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k in OBJ1){
                c = OBJ1[k];
                if(ACTIVE) ACTIVE.remove();
                BODY.append(c);
                ACTIVE = c;
            }
        }*/

        //TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.hide();
                c.show();
                ACTIVE = c;
            }
        }

        T2 = new Date().getTime();
        DELTA = T2 - T1;
        console.log('It took '+DELTA+' milliseconds');
    });
    </script>        
</body>

我用一些 Lorem Ipsum 和 Lorem Pixel 内容创建了 5 个通用元素,他们复制/粘贴了 3 次,形成了 15 个 1 级元素。

我隐藏和显露了 15 个元素中的每一个元素 1000 次。每次测试 3 次。

案例 1(目前获胜):5.2s、4.75s、4.85s

案例2:21.5s、21.5s、20s

@edit 3:更改案例 2 方法

将第二种情况从hide()/show() 更改为css() 可以大大提高性能。

//TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            _this.css('display','none');
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 15000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.css('display','none');
                c.css('display','block');
                ACTIVE = c;
            }
        }

还将循环增加到 15k。

案例1:6.5s左右

案例2:2.5s左右

【问题讨论】:

  • 只有四个元素,没关系。当您进入数千个时,您可能会看到明显的差异。 Measure it 可以肯定。这里还有其他需要考虑的事情。例如,您的元素之一包含img,因此您可能需要考虑是否要预加载图像资源。如果您使用脚本将img 注入到 DOM 中,那么在将元素添加到 DOM 之前它不会开始加载。
  • 有趣的结果。我还发现css('display')show()/hide() 快得多。这是我正在玩的性能测试;它比您的情况更简单,但仍然强调在这种情况下使用css() 显示/隐藏比删除和附加效果更好。见 jsperf:jsperf.com/dynamic-dom-performance
  • 在 Chrome、Firefox、IE 和 Edge 中看到一致的结果。 (有趣;browserscope 将 Edge 检测为 Chrome 42)

标签: javascript jquery html performance dom


【解决方案1】:

一定要把它留在 DOM 树中。我只会使用显示/隐藏方法来显示您想要的。

如果有一个动态变化的值应该反映在元素中,我只会使用 JS 方法,但如果它们都是静态的,那么更改 DOM 树的性能要重得多,而不仅仅是 CSS 样式更改。

您可以通过编写两者来进行测试,然后使用 jsperf 进行比较。

【讨论】:

    【解决方案2】:

    Javascript 是一种速度非常快的语言,但是 DOM 是一个巨大的瓶颈。因此,将数据保存在 Javascript 对象中会快得多,但您必须自己将活动元素渲染到 DOM(而不是仅仅让它可见)。

    我不会担心几十个元素的 DOM 速度很慢,但如果你有很多元素或试图对它们执行计算/过滤器,那么一定要使用 Javascript。

    【讨论】:

    • "但是您必须自己将活动元素呈现给 DOM(而不是仅仅让它可见)。"你是什​​么意思?您的意思是删除以前活动的元素,然后附加新活动的元素?
    • 您是否仍然认为 Javascript 更快,即使考虑到: 1- 所有元素都写入 HTML 文档,然后在页面加载时删除并存储在 javascript 对象中。 2- 每次活动元素更改时,我都会按照您的建议更改 DOM 结构,方法是删除当前活动元素,然后添加新元素。
    • 哦,如果你先将所有元素加载到 DOM 中,转换它,然后根据需要重新附加它们,这是个坏主意。
    • 我会例如将数据格式化为 JSON 并将其作为 data- 属性添加到页面上的某个元素上。那么页面上的元素就没有那么多了!
    【解决方案3】:

    我认为您可能想要应用延迟渲染的唯一 dom 元素是那些需要媒体内容(如图像、音频、视频等)的元素。对于那些,搜索延迟加载 js 库,当您显示该元素时加载该元素的内容。您也可以将元素加载到页面中并隐藏,但如果媒体元素过多,可能会占用内存。

    最后,您可以为此使用 React.js,因为它的主要工作是动态渲染两个 dom 树之间的差异,这可能会在您渲染相同 dom 元素但内容略有不同的场景中带来一些很大的改进。您可能知道这一点,您有什么理由决定在此上使用完整的 vainilla.js 吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-06
      • 2011-06-12
      • 2013-04-04
      • 2012-05-01
      • 2012-09-20
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多