JAvascriptパフォーマンス最適化


本文は主に私が『高性能Javascript』を読んだ後、いくつかの有用な最適化案を記録したいと思っています.そして、私自身の経験について、みんなで共有したいと思っています.
Javascriptのロードと実行
ブラウザがDOMツリーを解析するとき、scriptラベルを解析すると、jsファイルのダウンロード、解析の実行が完了するまで、他のすべてのタスクがブロックされることはよく知られています.したがって,このときブラウザはここでブロックされ,scriptタグをheadに入れると,このjsファイルのロード実行前にユーザは空白のページしか見えず,このようなユーザ体験は特に腐っているに違いない.これに対して、よく使われる方法は以下のとおりです.
  • は、すべてのscriptラベルをbodyの一番下に配置し、jsファイルが最後にロードされて実行されることを保証し、まずページをユーザーに表示することができます.しかし、まず、ページの最初のスクリーンレンダリングがjsファイルの一部に依存しているかどうかを明らかにする必要があります.もしそうであれば、jsファイルの一部をheadに置く必要があります.
  • はdeferを使用します.例えば、次のような書き方です.deferという書き方をすると、ブラウザがそのラベルを解析するときにも対応するjsファイルがダウンロードされますが、すぐに実行されるわけではなく、DOM解析が完了するまで(DomContentLoaderより前)これらのjsファイルが実行されます.したがって、ブラウザにブロックされません.
  • にjsファイルをロードします.このようにして、ページのロードが した 、 なコードをロードすることもできます.また、jsファイルの なロード/オンデマンドロードを することもできます. えば、 よく られるのは、webpackがvue-router/react-routerと してオンデマンドロードを し、 のルートにアクセスしたときにのみ、 するコードをロードすることです. な は の りである:
  • 1.scriptタグを に してスクリプトをロードします.たとえば、 のコードを します.
      function loadScript(url, callback) {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        //   IE
        if (script.readyState) {
          script.onreadystatechange = function () {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
              script.onreadystatechange = null;
              callback();
            }
          }
        } else {
          //           
          script.onload = function () {
            callback();
          }
        }
        script.src = url;
        document.body.append(script);
      }
    
      //     js
      loadScript('file.js', function () {
        console.log('    ');
      })

    2.xhr でjsファイルをロードしますが、この ではドメイン の に する があります. は のとおりです.
      const xhr = new XMLHttpRequest();
      xhr.open('get', 'file.js');
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
            const script = document.createElement('script');
            script.type = 'text/javascript';
            script.text = xhr.responseText;
            document.body.append(script);
          }
        }
      }

    3. のjsファイルを に し、 する. : 、ブラウザの くはjsファイルの ダウンロードをサポートしているが、 ダウンロードには の の がある(ブラウザベースでは のブラウザは4つしかダウンロードできない).また、jsファイルごとに のhttp を する があり、4つの25 KBのファイルをロードするのは100 KBのファイルをロードするよりも がかかる.したがって、 のjsファイルを じものに し、コード を うことが ましい.
    JAvascript ドメイン
    が されると、 が される を する コンテキストが されます. の が すると、この コンテキストは されます.したがって、 じ を び すと、 の コンテキストが されます. コンテキストごとに の ドメインチェーンがあります. ドメインというものはとっくに っていると いますが、1つの にとって、その の ドメインはその の です. の 、1つの に するたびに、 の ドメインチェーンを して の する を つけ、まず の を し、その 、 ドメインチェーンに ってレイヤごとに します.したがって、 の (グローバル )にアクセスすると、 の に アクセスするよりもパフォーマンスの が きくなります.したがって、よく されるグローバル をローカル に することができます.
    const a = 5;
    function outter () {
      const a = 2;
      function inner () {
        const b = 2;
        console.log(b); // 2
        console.log(a); // 2
      }
      inner();
    }

    オブジェクトの み み
    JAvascriptでは, に , , ,オブジェクトの4 に けられる. とローカル へのアクセスが も く、 とオブジェクトメンバーへのアクセスが い.オブジェクトメンバーにアクセスする は, ドメインチェーンと にプロトタイプチェーン(prototype) で する.したがって、 したメンバーがプロトタイプチェーンの に すぎると、アクセス が くなります.したがって、オブジェクトメンバーの とネストの さをできるだけ らす があります. えば のコード
      //           
      function hasEitherClass(element, className1, className2) {
        return element.className === className1 || element.className === className2;
      }
      //   ,         ,                
      function hasEitherClass(element, className1, className2) {
        const currentClassName = element.className;
        return currentClassName === className1 || currentClassName === className2;
      }

    DOMオペレーション
  • はDOMの を し、できるだけjavascriptで し、できるだけ を してDOMノードを する.たとえば、 のコード:
  •   //    ,        ,    id t   ,      innerHTML
      function innerHTMLLoop () {
        for (let count = 0; count < 15000; count++) {
          document.getElementById('t').innerHTML += 'a';
        }
      }
      //    ,
      function innerHTMLLoop () {
        const tNode = document.getElemenById('t');
        const insertHtml = '';
        for (let count = 0; count < 15000; count++) {
          insertHtml += 'a';
        }
        tNode.innerHtml += insertHtml;
      }
  • は と をできるだけ らすことができ、 と の は に になる があるため、 の を らすために、 の
  • を うことができる.
    1.Domのスタイルを する は、できるだけすべての を し、 に して、 と の を らす があります.
      //    
      const el = document.getElementById('test');
      el.style.borderLeft = '1px';
      el.style.borderRight = '2px';
      el.style.padding = '5px';
    
      //    ,       ,                
      const el = document.getElementById('test');
      el.style.cssText += '; border-left: 1px ;border-right: 2px; padding: 5px;'

    2.DOMノードを して する は、DOMノードを にして、 の を い、 で に することで、 2 の が になります. な は の りです.
      //     
      const ele = document.getElementById('test');
      //    dom    
    
      //      ,             ,        ,           ,         
      const ele = document.getElementById('test');
      ele.style.display = 'none';
      //    dom    
      ele.style.display = 'block';
    
      //      ,          (documentFragment),          ,             ,                     ,          。。
      const fragment = document.createDocumentFragment();
      const ele = document.getElementById('test');
      //    dom    
      ele.appendChild(fragment);

    3.イベント の :イベント は、ターゲットノードのイベントを ノードに して します.ブラウザのバブルの により、ターゲットノードがイベントをトリガーすると、 ノードもイベントをトリガーします.したがって、 ノードがイベントの と を します.
    では、その はどこにあるのでしょうか.リストがあるとします. リスト は じイベントをバインドする がありますが、このリストは に され、 される があります. の では、 リスト・アイテムにイベント・プロセッサをバインドするしかありません.また、 しいリスト・アイテムを するたびに、 しいリスト・アイテムに しいイベント・プロセッサを する があります.これにより、リスト が きいと、 に くのイベントプロセッサが し、パフォーマンスに きな が します.イベント により,リスト の ノードでこのイベントを し,それによって に すればよい.これにより、 リスト についても の は ありません.また、イベント の い も です.
    function handleClick(target) {
      //           
    }
    function delegate (e) {
      //             
      if (e.target.nodeName === 'LI') {
        handleClick(e.target);
      }
    }
    const parent = document.getElementById('parent');
    parent.addEventListener('click', delegate);

    の は-> のブログの で、startあるいはfollowに します