少し前に、会社の既存プロジェクトの JavaScript コードを最適化しました。この記事は、最適化作業の概要をまとめたものです。もちろん、私の最適化方法が最適ではないかもしれませんし、何か間違っているかもしれません。アドバイスをお願いします。
JavaScriptの最適化概要は以下のポイントに分かれています
最適化前後の比較
最適化前
最適化後
コードがわかりにくく、同じ機能の関数が複数箇所に繰り返し登場します。実装を変更する必要がある場合は、すべての場所を見つける必要があります。モジュール化、パブリック インターフェイスの抽出とライブラリへの編成。明確な構造、便利なコードの再利用、さまざまな汚染問題を防止する機能を備えています。
JavaScript ファイルのサイズは比較的大きく、読み込みによりネットワーク時間が消費され、ページのレンダリングがブロックされます。
● サイズは比較的小さく、ネットワークの読み込み時間は最適化されます。 ● 圧縮によりコードがある程度混乱します。保護されたコード
を使用すると、複数の個別の JavaScript ファイルをロードする必要があるため、http リクエストの数が増加し、パブリック ライブラリをマージして圧縮すると、http リクエストの数が減り、サイズが削減されます。
ドキュメントの欠如(後続の開発者が既存の関数を理解できるようにする) 関数が明確ではないため、前述したように同じ機能を持つ関数が複数の場所で繰り返し出現するという事実がある程度発生します) の各クラス、関数、属性パブリック ライブラリにはドキュメントがあります
● モジュール化 (クラス プログラミング): コード 変数汚染の問題を明確かつ効果的に防止し、コードの再利用により拡張が容易になります
● JavaScript の圧縮と難読化: サイズの削減、読み込み時間の最適化、コードの難読化と保護。 ;
● JavaScript ファイルのマージ: ネットワークにかかる時間を削減し、パフォーマンスを向上させます。
● ドキュメントの生成: パブリック ライブラリを使用するのが便利で、インターフェイスを見つけやすいです。
モジュール化 (クラス プログラミング)
静的クラスの場合、JavaScript の実装は Object を直接使用するだけで十分ですが、インスタンス化され継承可能なクラシック クラスを作成するには多大な労力がかかります。 JavaScript はプロトタイプベースのプログラミング言語であり、組み込みクラスの実装が含まれていないため (アクセス制御文字がなく、クラスを定義するためのキーワード class がなく、継承のための extend またはコロンをサポートしていません)、仮想関数 (virtual など) をサポートすることは役に立ちませんが、JavaScript を使用して古典的なクラスを簡単にシミュレートできます。
静的クラス
Baby JSパブリックインターフェースの特性上、インスタンス化する必要がないため、最適化のためにこのメソッドが使用されます。以下では、実装を紹介する例として PetConfigParser を使用しています。
var PetConfigParser;
if (!PetConfigParser) {
PetConfigParser = {};
}
(function () {
// private 変数 , function
/**
* [cate * 10000 + (lvl - 1) * 10 + dex - 1] をキーとするすべての赤ちゃん設定辞書
* @attribute petDic
* @type {Object}
* @private
*/
var petDic = null; //赤ちゃん辞書
/**
* __pet_config に基づいて、cate、dex、lvl の組み合わせをキーとしてオブジェクト辞書を構築します
* @method buildPetDic
* @private
* @return {void}
*/
function buildPetDic() {
petDic = new Object () ;
for (__pet_config の var item) {
var lvl = parseInt(__pet_config[item]['lvl']);
var dex = parseInt(__pet_config[item]['dex']);
var cate = parseInt(__pet_config[item]['cate']); var key = cate * 10000 + (lvl - 1) * 10 + dex }
}
//パブリックインターフェース
/**
* 赤ちゃんIDに基づいて、__pet_configで対応する赤ちゃん情報を読み取ります
* @method getPetById
* @param {String/int} petId baby id
* @return {Object} pet 赤ちゃんのすべての静的情報, {id:「300003289」、lvl:「1」、dex:「2」、price:「200」、life:「2592000」、cate:「3」、name:「フライングエンジェル レベル1 熟練度2」など、イントロ:「」、スキル:「タリスマン」、スキル1_確率:「30」、スキル2_確率:「0」}
*/
if (typeof PetConfigParser.getPetById !== 'function') {
Id = function (petId) {
var pet = ("未定義" == typeof (__pet_config)) ? null : __pet_config["pet_" + petId];
️ペットを返します。要約すると、上記のプロセスは次のステップに分かれています: 1) グローバル変数 (var PetConfigParser) を定義します。変数の最初の文字と通常の変数の違いに注意してください。2) 次に、匿名変数を作成します。関数を作成して実行します ((function () {/*xxxx*/ })(); )、現在のスコープ内でのみアクセスできるローカル変数と関数を匿名関数内に作成します 3) グローバル変数 (var; PetConfigParser) にどこからでもアクセスできるようにするには、無名関数内に PetConfigParser を操作するための静的関数を追加します。 使用例: $(function () {DialogManager.show ("#msgBoxTest", "#closeId");
DialogManager を返します。 ; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ コンストラクタメソッド; ● プロトタイプメソッド; ● コンストラクタ + プロトタイプの混合メソッド コンストラクタメソッド コンストラクタを使用しますインスタンス オブジェクトのプロパティと値を初期化します。任意の JavaScript 関数をコンストラクターとして使用できます。新しいインスタンスを作成するには、コンストラクターの前に new 演算子を付ける必要があります。 var person = function (name) { this.name = name; this.sayName = function(){alert(this.name); };}
//インスタンス化 var tyler = new Person("tylerzhu");varsaylor = new Person("saylorzhu");tyler.sayName();saylor.sayName();// チェックtheinstancealert(tylerinstanceofPerson);コンストラクターメソッドは従来のオブジェクト指向言語に慣れていますか? class キーワードが function に置き換えられるだけです。 注: new を省略しないでください。それ以外の場合は、Person("tylerzhu") //==>未定義です。 new キーワードを使用してコンストラクターを呼び出すと、実行コンテキストがグローバル オブジェクト (ウィンドウ) から、新しく生成されたインスタンスを表す空のコンテキストに変わります。したがって、this キーは現在作成されているインスタンスを指します。したがって、new が省略され、コンテキスト スイッチが実行されない場合は、グローバル オブジェクト内で name が検索され、見つからない場合は、グローバル変数名が作成され、unknown が返されます。 プロトタイプメソッドコンストラクターメソッドはシンプルですが、メモリを無駄に消費するという問題があります。たとえば、上記の例では、tyler と Saylor という 2 つのオブジェクトがインスタンス化されているように見えますが、実際には、各インスタンス オブジェクトの SayName() メソッドの内容はまったく同じです。インスタンスが生成されると、アプリケーションのコンテンツを繰り返す必要があります。 alert(tyler.sayName ==saylor.sayName) は false を出力します! ! ! JavaScript のすべてのコンストラクターには、別のオブジェクトを指すプロトタイプ属性があります。このオブジェクトのすべてのプロパティとメソッドは、コンストラクターのインスタンスによって共有されます。 var person = function (name) { Person.prototype = name; Person.prototype.sayName = function(){alert(this.name); }}
//インスタンス化var tyler = new person("tylerzhu");var Saylor = new person("saylorzhu");tyler.sayName();saylor.sayName();
//インスタンスを確認しますalert(tylerinstanceofPerson);この時点では、tylerインスタンスとsaylorインスタンスのsayNameメソッドは両方とも同じメモリアドレス(プロトタイプオブジェクトを指している)にあるため、プロトタイプメソッドはメモリを節約します。 しかし、 tyler.sayName();saylor.sayName(); の出力を見ると、問題がわかります - どちらも「saylorzhu」を出力します。プロトタイプのすべてのプロパティは共有されるため、1 つのインスタンスが変更されると、他のインスタンスもそれに応じて変更され、インスタンス化されたオブジェクト Saylor が Tyler をオーバーライドします。 コンストラクター+プロトタイプの混合メソッド
コンストラクター メソッドは、同じクラスの各オブジェクトに異なるメモリを割り当てることができます。これは、クラスを作成するときにプロパティを設定するのに非常に適していますが、メソッドを設定する場合は、同じクラスの異なるオブジェクトに同じメモリを共有させる必要があります。方法はプロトタイプを使用することです。したがって、クラスを作成する場合は、コンストラクター メソッドとプロトタイプ メソッドを混在させる必要があります (多くのクラス ライブラリが提供するクラス作成メソッドやフレームワークのクラス作成メソッドは、基本的にコンストラクター + プロトタイプです)。
var person = function (name) {
Person.prototype = name;
Person.prototype.sayName = function(){
alert(this.name);
}
}
//インスタンス化
var tyler = 新しい人("tylerzhu");
var Saylor = 新しい人("saylorzhu");
tyler.sayName();
saylor.sayName();
/ /インスタンスを確認してください
alert(tyler instantof Person);
この方法では、コンストラクターを介して異なる名前を持つ人物を構築でき、オブジェクトのインスタンスもsayNameメソッドを共有するため、メモリの無駄が発生しません。
JavaScript の圧縮/マージ
JavaScript コードの圧縮と難読化の意味: 簡単に言うと、js ファイルのサイズを削減し、冗長なコメント、改行、インデントなどを削除して、ダウンロードを高速化し、ユーザー エクスペリエンスを向上させることです。
JavaScript 圧縮ツールは数多くありますが、圧縮パフォーマンスが非常に優れているため、現在 jQuery で使用されているツールである UglifyJS を使用することをお勧めします (jQuery は以前にも Packer などのさまざまな圧縮ツールを使用していました)。
「jQuery 1.5 がリリースされたとき、John Resig 氏は、使用されるコード オプティマイザーが Google Closure から UglifyJS に切り替えられ、新しいツールの圧縮効果は非常に満足のいくものであったと述べました。」