メンテナンス可能なJavaScriptを作成します.グローバル変数

3770 ワード

JavaScript実行環境は多くの面で独特なところがあります.大域変数と関数の使用はその一つです.実際には、JavaScriptの初期実行環境は多様なグローバル変数によって定義されています.これらの大域変数はスクリプト環境の創建当初から存在しています.これらは全体のオブジェクトにマウントされています.
ブラウザでは、windowオブジェクトはしばしば全体のオブジェクトと同じです.したがって、グローバルスコープで宣言された変数と関数はすべてwindowオブジェクトの属性です.以下のように、両方はwindowオブジェクトの属性です.
var color = 'red';
 
function showColor () {
    alert(color);
}

console.log(window.color);    // 'red'
console.log(typeof window.showColor);    // 'function'
1.グローバル変数による問題
一般的には、グローバル変数の作成は悪いこととされています.特にチーム開発の大きな背景においてはなおさらです.
名前の衝突:スクリプトの大域変数と大域関数が増えたとき、ネーミング競合が発生する確率も大きくなります.このように、グローバル変数カラーとグローバル関数showColor()は同じファイルにある場合が良いですが、グローバル変数とグローバルオブジェクトを多く引用する場合、追跡はかなり面倒になります.
コードは脆弱です.グローバル変数に依存する関数はコンテキスト環境に深く結合されています.環境が変わると関数が失効する可能性があります.
予期しないグローバル変数:var文で宣言されていない変数に値を与えると、JavaScriptは自動的にグローバル変数を作成します.特に、意図しないで作成したグローバル変数とシステム定義のグローバル変数は同時にシステムのグローバル変数の値を変更します.以下のとおりです
function doSomething () {
    var count = 10;
        title = "Maintainable JavaScript";    //       ,       
}
2.グローバル変数による問題を解決する
a.予期せぬグローバル変数を避ける
予期しないグローバル変数はJSLintやJSHintなどの検出ツールを使ってもいいし、JSの厳格なモードを使って、JavaScriptエンジンがコードを実行する前に、より厳格なエラー処理と文法検査を実行するようにJSの厳格なモードを使って通知します.ルールの一つは、宣言されていない変数の割当動作を検出することができる.
b.単一グローバル変数
グローバル変数の意味は、グローバル変数を作成するだけです.JQueryのように2つの特定のグローバル変数を定義しています.$とjQueryは、$が他のクラスに使用された場合に限って、衝突を避けるためにjQueryを使うべきです.
「単一グローバル変数」とは、作成されたこの唯一のグローバルオブジェクト名が唯一無二であり、すべての機能コードをこのグローバルオブジェクトにマウントするという意味です.したがって、各可能なグローバル変数は、あなたの唯一のグローバルオブジェクトの属性となり、複数のグローバル変数を作成しません.
c.名前空間
あなたのコードが一つのグローバルオブジェクトであっても、グローバル汚染の可能性があります.単一グローバル変数モードを使用するほとんどの項目は、同様に「名前空間」という概念を含んでいます.名前空間は、グローバルオブジェクトの単一の属性によって簡単に表される機能グループである.機能を名前空間によってグループ化することで、グローバルオブジェクトが整然としていると同時に、チームメンバーに新しい機能がどの部分に属するべきかを知ることができます.
既存のjsでは元の名前空間をサポートしていません.JSで作成したどのオブジェクトもデフォルトはグローバルオブジェクトです.現代の大規模なJS開発において、名前空間を採用しないと非常に悪いネーミング方法になり、コードの醜さが読み取り不能になる.サードパーティライブラリを導入すると、明らかに上書きされる場合があります.
消えやすいのは、ES 6には、nativeの名前空間がありますが、今は特別な手段が必要です.名前空間の概念を模擬するために.簡単に言えば、すべての関連関数と変数をパッケージ化する簡単な字面量を作成します.この簡単な対象の字面量は名前空間の役割をシミュレーションした.
var NAMESPACE = {
    person: funnction(name) {
        this.name = name;
        this.getName = function() {
            return this.name;
        }
    }
}

//     
var p = new NAMESPACE.person("andy");
p.getName()
そうすると、私たちは名前空間を通して複数のpersonオブジェクトを宣言することができます.しかし、ここではもう一つの問題があります.私達がここで使っているのはグローバルオブジェクトです.この「名前空間」を追加すると、グローバル空間の同名のオブジェクトをカバーすることができます.したがって、名前空間を宣言する前に、全体の安全を確保する必要があります.
//          ,           。
var NAMESPACE = NAMESPACE || {};
グローバル空間に同名のオブジェクトが既に存在する場合、そのオブジェクトは上書きされません.さもなくば、新しい名前空間を作成します.この安全な名前空間を採用した後、声明の方法も一部変更する必要があります.
var NAMESPACE = NAMESPACE || {};

MYNAMESPACE.person = function(name) {
    this.name = name;
};

MYNAMESPACE.person.prototype.getName = function() {
    return this.name;
};

//     
var p = new MYNAMESPACE.person("ifcode");
p.getName();        // ifcode
名前空間構造関数を定義するには、プロトタイプに定義する必要があります.そうでないと、新規作成したインスタンスはオブジェクトにアクセスできない方法です.
d.モジュール化
もう一つの単大域変数に基づく拡張方法はモジュールであり、モジュールは汎用的な機能セグメントであり、新たな大域変数または名前空間を作成していない.逆に、これらのコードは、タスクを実行するか、言い訳を発行するかを示す単一関数に保存されます.このモジュールは一つの名前で表してもいいです.このモジュールは他のモジュールに依存してもいいです.
e.ゼログローバル変数
この方法は場面が多くないので、特別なシーンでのみ適用されます.最も一般的なシナリオは、他のスクリプトにアクセスされない完全に独立したシナリオである.このようなシナリオが存在するのは、必要なすべてのシナリオが一つのファイルにマージされるからであるか、またはこの非常に短いため、言い訳のないコードが一つのページに挿入され、最も一般的な使い方はブックマークを作成するためである.
ブックマークは独立しています.ページに何が含まれているかは分かりません.ページでその存在を知る必要はありません.最終的には、「ゼログローバル変数」のシナリオをページに埋め込む必要があります.実現方法は、即座に実行される関数を使って呼び出し、すべてのスクリプトを配置することです.
(function (win)) {
    var doc = win.document;
    
    //           

    //       
}
このコードはページに注入されても大域変数は生成されません.その後、関数を厳密モードに設定することで大域変数の作成を回避できます.