DOM操作の最適化によるJavaScriptチューニングにチャレンジ!

2013/09/26

HTML5エキスパートで有名な吉川さん(同性w)からCodeIQの問題があったので挑戦!

DOM操作の最適化によるJavaScriptチューニングにチャレンジ!

オリジナル


    var button = document.querySelector('button'),
        ul = document.querySelector('#output'),
        itemCount = 0;

    function addItems() {
      for ( var i = 0; i < 10; i++ ) {
        itemCount++;
        ul.innerHTML += '
  • ' + '

    アイテム' + itemCount + '

    ' + '

    詳細' + itemCount + '

    ' + '
  • '; } }

    30分くらいでざっとコーディングして提出

    提出コード

    
        var button = document.querySelector('button'),
            ul = document.getElementById('output'),
            itemId = 0;
    
        var itemTemplate = '';
        var addCount = 10;
        var output = document.getElementById("output");
    
        function createItem() {
            itemId++;
            var item = new Object();
            item.title = 'アイテム' + itemId;
            item.detail = '詳細' + itemId;
            return item;
        }
    
        function loadItemTemplate(item) {
            var li = document.createElement('li'); 
            var article = document.createElement('article');
            var h1 = document.createElement('h1');
            var p = document.createElement('p');
    
            article.setAttribute('class', 'item');
            h1.setAttribute('class', 'title');
            p.setAttribute('class', 'detail');
    
            h1.textContent = item.title;
            p.textContent = item.detail;
    
            article.appendChild(h1);
            article.appendChild(p);
            li.appendChild(article);
            return li;
        }
    
        function addItems() {
          for ( var i = 0; i < addCount; i++ ) {
            itemTemplate = loadItemTemplate(createItem());
            document.getElementById('output').appendChild(itemTemplate);
          }
        }
    

    テンプレートのHTML生成がループしてるので無駄だなと思いつつ、この程度だと計測時間が変わらなかったのでとりあえず。

    丁寧にアドバイスを頂きました。

    • Document Fragmentを経由
    • getElementById()は高コストなのでキャッシュする

    提出コード

    
        var button = document.querySelector('button'),
            ul = document.getElementById('output'),
            itemId = 0;
    
        var template;
        var addCount = 10;
        var li;
        var article;
        var h1;
        var p;
    
        loadItemTemplate();
    
        function createItem() {
            itemId++;
            var item = new Object();
            item.title = 'アイテム' + itemId;
            item.detail = '詳細' + itemId;
            return item;
        }
    
        function loadItemTemplate() {
            template = document.createElement('li'); 
            article = document.createElement('article');
            h1 = document.createElement('h1');
            p = document.createElement('p');
    
            article.setAttribute('class', 'item');
            h1.setAttribute('class', 'title');
            p.setAttribute('class', 'detail');
    
            article.appendChild(h1);
            article.appendChild(p);
            template.appendChild(article);
        }
    
        function bindItem(item) {
            h1.textContent = item.title;
            p.textContent = item.detail;
            var itemRow = template.cloneNode(true);
            ul.appendChild(itemRow);
        }
    
        function addItems() {
          for ( var i = 0; i < addCount; i++ ) {
              bindItem(createItem());
          }
        }
    

    cloneNode()を利用してみたけど、なんかViewの分離がちょっと汚くなっちゃたかな? insertNode()とかを使って、ツリーを操作した方がスムーズなのかも。