web-dev-qa-db-ja.com

JavaScriptでオブジェクトの名前空間をどのように保護できますか?

前の質問の続き: プロトタイプベースを理解するためのJavascriptの簡単なコードOOP basics コンソールでこの2つの個別のオブジェクトを実行するとします(それらが子と呼ばれ、親の間には継承はありません):

var parent = {
    name: "parent",
    print: function(){
       console.log("Hello, "+this.name);
    }
};

var child = {
    name: "child",
    print: function(){
       console.log("Hi, "+this.name);
    }
};

parent.print()
// This will print: Hello, parent
child.print()
// This will print: Hi, child

temp =parent;
parent = child;
child = temp;


parent.print()
// This will now print: Hi, child
child.print() 
// This will now print: Hello, parent

次に、親がライブラリであると仮定します。これは、ブラウザのHTML5アプリケーションとして、サンドボックスで実行されているため、それほど害を及ぼすことはありませんが、ChromeOS、FirefoxOS、およびその他の[ブラウザ] OSの登場により、ネイティブにもリンクされます。 API、それは「サンドボックス」からの脱却です。これで、誰かが名前空間を変更した場合、名前空間が変更された場合、コードレビューアー(自動化されているかどうかにかかわらず)が誤った使用を見つけるのは困難です。

私の質問は次のようになります:上記の状況を実行できる方法はたくさんありますか?この名前空間を保護するために何ができるでしょうか? (JavaScript自体または静的コード分析ツールのいずれかで)

6

グローバル変数を保護するために(すべてのブラウザーで)実行できることはほとんどありません。

ただし、一般的な(良い)方法は、すべてのスクリプトを( [〜#〜] iife [〜#〜] )関数クロージャにカプセル化することです。

(function() {
    var parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    var child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    parent.print()
    // This will print: Hello, parent
    child.print()
    // This will print: Hi, child
})();

つまり、その関数のスコープ内ではparentchildのみを使用できます。それは限界ですが、それも保護しています。それらをグローバルに必要とする場合、1つのオプションは名前空間オブジェクトを維持することです。

var myGlobals = {};

(function( global ) {
    global.parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    global.child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    global.parent.print()
    // This will print: Hello, parent
    global.child.print()
    // This will print: Hi, child
})(myGlobals);

または、個別のグローバルとして本当に必要な場合は、次のようにすることができます。

(function() {
    window.parent = {
        name: "parent",
        print: function(){
           console.log("Hello, "+this.name);
        }
    };

    window.child = {
        name: "child",
        print: function(){
           console.log("Hi, "+this.name);
        }
    };

    parent.print()
    // This will print: Hello, parent
    child.print()
    // This will print: Hi, child
})();

しかし、それはあなたをスクエアワンに戻します。この場合、シャッフル時にこれらの変数を保護するために何かを行うことを確認する必要があります。書く代わりに:

temp =parent;
parent = child;
child = temp;

あなたは書くことができます:

(function( parent, child ) {

    // Do some stuff.

    // Note: parent and child are references,
    // although they are switched, something like:
    //    child.hello = "hello";
    // will still edit the `parent` object in the outer scope

})(child, parent); // Pass them in swapped.

FreezeSeal (2つの新しいJS Objectメソッド)は、問題を正確に解決していないか、クロスブラウザーのサポートがまだないにもかかわらず、このスレッドで注目に値します。

11
Jacob Swartwood