High performence javascript(高性能JavaScript)

9729 ワード

本オススメ指数:4星
第一章ロードと実行
  • ブラウザは、単一のスレッドを使用して、ユーザインターフェース(UI)のリフレッシュとJavaScriptスクリプトを処理しています.同じ時間に一つのことしかできません.ブラウザがJavaScriptコードを実行する時、対応するユーザがボタンを押したり、UIを更新したりするような他のことはできません.
  • JavaScriptコードが埋め込まれていても、外部ファイルに含まれていても、ページのダウンロードとレンダリングは停止してスクリプトの実行が完了するまで待つ必要があります.
  • ブラウザーはすべてjsファイルを並列にダウンロードすることができますが、jsダウンロードの過程では依然として他のリソースのダウンロードをブロックします.スクリプトのダウンロードプロセスは相互に影響しませんが、ページはすべてのjsコードをダウンロードして実行してから続けます.
  • ブロックなしのスクリプト:
  • deferとasyncです.同じ点は並行ダウンロードを採用しており、ダウンロード中はブロックされません.違いは実行のタイミングです.asyncはロードが完了したらすぐに自動的に実行します.deferは並行してダウンロードしてからonloadイベントを実行する前に実行します.(注意基準規定のdeferは外部シナリオでしか機能しない)
  • ダイナミックスクリプト要素:
    var script = document.createElement("script");
    script.type = "type/javascript";
    script.src = "xxx.js";
    document.getElementsByTagName("head")[0].appendChild("script");
    テキストは、ページに追加された時点でダウンロードを開始し、直ちに実行されるが、ページの他のプロセスをブロックすることはない.
  • XMLHttpRequestスクリプト注入は、XMLHttpRequestオブジェクトを用いてスクリプトを取得し、ページに注入される
    var xhr = new XMLHttpRequest();
    xhr.open("get", "file1.js", true);
    xhr.onreadystatechange() {
        if(xhr.readyState == 4) {
            if(xhr.staus >= 200 && xhr.status < 300 || xhr.status == 304) {
                var script = document.createElement("script");
                script.type = "type/javascript";
                script.text = xhr.responseText;
                document.body.appendChild(script);
            }
        }
    }
  • .
    データ・アクセス
    jsには4つの基本的なデータアクセス位置があります.
  • 文字数:文字列、数字、ブール値、オブジェクト、配列、関数、正規表現、null、undefined
  • ローカル変数:varで定義されたデータ記憶部
  • 配列要素:js配列オブジェクト内部に格納され、数字をインデックス
  • とする.
  • オブジェクトのメンバー:jsオブジェクトの内部に格納され、文字列を索引の字面量とローカル変数のアクセス速度は、配列項目と対象メンバーのアクセス速度よりも速い
  • 識別子解析の性能:
  • の識別子の位置が深いほど、読み取りの速度が遅くなります.したがって、関数でローカル変数を読み出すのは常に一番早いですが、グローバル変数を読むのはいつも一番遅いです.
  • 作用領域にまたがる値が関数で1回以上引用された場合、それを局所変数に格納する.
  • スコープチェーンを変更:
  • with
  • try-catch文のcatchは、それらの本質は、新しい変数オブジェクトを作用するドメインチェーンのヘッダに挿入し、関数の局所変数は第二の作用するドメインチェーンオブジェクトの中にあるので、アクセスの価格はより高い.withを使用すると、新しい変数オブジェクトが作成されます.これはパラメータで指定されたオブジェクトのすべての属性を含んでいます.このオブジェクトは、スコープのヘッダに押し込まれます.catch従文は、誤ったオブジェクトを作用ドメインチェーンのヘッダ
  • に挿入することである.
    DOMプログラミング
    ドキュメントオブジェクトモデル(DOM)は、XMLとHTMLドキュメントを操作するためのプログラムインターフェースであり、DOM APIを使用してドキュメント内のデータ操作DOMにアクセスするのは遅いです.DOMとECMAScriptを島にたとえると、それらの間は有料ブリッジで接続されています.ECMAScriptはDOMにアクセスするたびにコストがかかります.最適な実践:DOMにアクセスする回数を減らして、演算をできるだけECMAScriptのこの端に残して処理します.
    要素ノードのAPIのみを返します.
    コメントとテキストノードを無視する(通常は2つのノード間の空白にすぎない)
    children                childNodes
    childElementCount       childNodes.length
    firstElementChild       firstChild
    lastElementChild        lastChild
    nextElementSibling      nextSibling
    previousElementSibling  previousSibling
    効率的なセレクタAPIを使用する
    querySelector();querySelectorAll();
    描き直しと並べ替え
    ブラウザは、ページ内のすべてのコンポーネントをダウンロードした後、2つの内部データ構造を生成します.DOMツリー:ページ構造レンダリングツリーを表します.DOMノードはどのように表示しますか?
    DOMツリーのうちの1つのノードは、少なくともレンダリングツリーのうちの1つのノード(隠しDOM要素はレンダリングツリーに対応するノードがない)に対応しています.DOMツリーとレンダリングツリーの構築が完了したら、ブラウザは、ページ要素の描画を開始します.再配置する必要はなく、再描画をトリガするだけです.
    再配置はいつ発生しますか?
  • 可視DOM要素
  • を追加または削除する.
  • 元素位置変更
  • 元素サイズ変更(margin、border、padding、width、height変化など)
  • コンテンツの変更:テキストの変更または画像は他の異なるサイズの画像によって代替される
  • ページレンタ初期化
  • ブラウザのウィンドウサイズ変更
  • 再配置と再描画を最小化する
    スタイルを変更する:cssTextまたはcssクラスを使用する
            var el = document.getElementById("mydiv");
            el.style.borderLeft = "1px";
            el.style.borderRight = "2px";
            el.style.padding = "5px";
    
            //  :  cssText
            var el = document.getElementById("mydiv");
            el.style.cssText = "border-left: 1px; border-right: 2px; padding: 5px;";
    
            //       :  js  css ,  js css  
            var el = document.getElementById("mydiv");
            el.className = "xxx";
            //el.classList.toggle("xxx");
    DOM元素を大量に修正し、並べ替えと描き直しを減らす.
    ステップ:
  • により、文書ストリーム
  • から要素を逸脱させる.
  • .要素に多重変更を適用する
  • .
  • は、要素をドキュメントに持ち帰る
  • .
    要素を文書フローから逸脱させる3つの方法があります.要素を隠し、修正を適用して、2を再表示します.ドキュメントの断片を使って、DOMの外にサブツリーを作成して、ドキュメント3にコピーします.元の要素をドキュメントから離れるコピーにコピーして、コピーを修正して、完成したら元の要素を置換します.
    クイック対応のユーザーインターフェースを作成します.
    jsの単一の実行タスクは100 msを超えないようにしてください.そうでないと、ユーザーは明らかに遅いと感じます.
    解決方法:1.タイマーを使ってタスクを分割する2.ワーカーを使ってUIスレッドの外でコードを実行する(マルチスレッドを作成する)
    プログラミング実戦
    ダブルシークを避ける
    jsでコードを含む文字列を実行するには、4つの方法があります.1.eval()2.function()コンストラクタ3.setTiement()4.set Interval()彼らはjsコード文字列に入ることを許可し、それを実行します.
    var num1 = 1,
        num2 = 2,
    resEval = eval("num1 + num2");
    resFunction = new Function("arg1", "arg2", "return arg1 + arg2");
    function sum() {
        console.log(num1 + num2);
    };
    console.log(resEval);
    console.log(resFunction(num1, num2));
    
    setTimeut(sum, 1000);       //              
    setTimeout("sum()", 1000);
    //setInterval()    
    以上の4つの方法はいずれもJavaScriptコードの中で別のセグメントJavaScriptコードを実行していますが、今回はダブルシークの性能消費を引き起こしました.このコードはまず正常に値を求めます.そして実行中に文字列に含まれるコードに対して別の求値演算を開始します.
    オブジェクトではなくObject/Aray直接量を使う
    オブジェクトの字面量と配列の字面量の運行が速くなり、コード量の節約に役立ちます.
    重複した仕事を避ける
    時間処理時のeventUtilの対象を覚えていますか?
    addHandler: function(element, type, handler) {
            if(element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else if(element.attachEvent) {
                element.attachEvent('on'+type, handler);
            } else {
                element['on'+type] = handler;
            }
        },
        /*
                       addHandler             ,     
                  ,         ,                      。                   。
    
        addHandler: function(element, type, handler) {
            //    
            if(element.addEventListener) {
                addHandler = function(element, type, handler) {
                    element.addEventListener(type, handler, false);
                }
            } else if(element.attachEvent) {
                addHandler = function(element, type, handler) {
                    element.attachEvent('on'+type, handler);
                }
            } else {
                addHandler = function(element, type, handler) {
                    element['on'+type] = handler;
                }
            }
            //    
            addHandler(element, type, handler);
        },*/
    ビット演算を使ってスピードを上げる
    ビット別&とビット別または|によるビット別または^パリティ判断
    var i = 5;
    if(i % 2) {             //odd
        console.log("odd");
    } else {                //even
        console.log("even");
    }
    
    //         !
    if(i & 1) {             //odd
        console.log("odd");
    } else {                //even
        console.log("even");
    }
    /**
            ,       1, 1&    1(true)
            ,       0, 1&    0(false)
     */