web-dev-qa-db-ja.com

JavaScriptの名前空間とクラスを適切に設定する方法は?

JavaScriptアプリケーションを設定するには非常に多くの方法があるので、どちらが正しいか最良かについては混乱を招くようです。以下のテクニックに違いはありますか、これを行うより良い方法はありますか?

MyNamespace.MyClass = {
    someProperty: 5,
    anotherProperty: false,

    init: function () {
        //do initialization
    },

    someFunction: function () {
        //do something
    }
};

$(function () {
    MyNamespace.MyClass.init();
});

別の方法:

MyNamespace.MyClass = (function () {
    var someProperty = 5;
    var anotherProperty = false;

    var init = function () {
        //do something
    };

    var someFunction = function () {
        //do something
    };

    return {
        someProperty: someProperty
        anotherProperty: anotherProperty
        init: init
        someFunction: someFunction
    };
}());

MyNamespace.MyClass.init();

最初のテクニックfeelsよりクラスに似ています。これが違いを生むのであれば、サーバーサイドのバックグラウンドから来ています。 2番目の手法はより冗長で少し扱いに​​くいように見えますが、これも多く使用されているようです。誰かが光を当てて前進するための最善の方法をアドバイスしてください。たくさんのクラスが互いに話し合っているアプリケーションを作りたい。

41
TruMan1

どちらもしないでください。

JavaScriptの「クラス」を作成します。

var MyClass = function () {

    var privateVar; //private
    var privateFn = function(){}; //private 

    this.someProperty = 5;  //public
    this.anotherProperty = false;  //public
    this.someFunction = function () {  //public
        //do something
    };

};

MyNamespace.MyClass = new MyClass();

静的変数を持つもの:

var MyClass = (function(){

    var static_var; //static private var

    var MyClass = function () {

        var privateVar; //private
        var privateFn = function(){}; //private 

        this.someProperty = 5;  //public
        this.anotherProperty = false;  //public
        this.someFunction = function () {  //public
            //do something
        };
    };

    return MyClass;

})();

MyNamespace.MyClass = new MyClass();

「コンストラクター」を使用すると(すべての例には「コンストラクター」があり、この1つには処理するパラメーターがあります):

var MyClass = function (a, b c) {

    //DO SOMETHING WITH a, b, c <--

    var privateVar; //private
    var privateFn = function(){}; //private 

    this.someProperty = 5;  //public
    this.anotherProperty = false;  //public
    this.someFunction = function () {  //public
        //do something
    };

};

MyNamespace.MyClass = new MyClass(1, 3, 4);

上記のすべてを使用すると、できる

MyNamespace.MyClass.someFunction();

しかし、あなたはできない(外部から):

MyNamespace.MyClass.privateFn(); //ERROR!
63
Neal

最初の例は、単純に オブジェクトリテラル です。インスタンス化できず、プライベートメンバーがありません。 2番目の例には、いくつかの誤った構文(var someProperty: 5var someProperty = 5)ただし、クロージャを使用して、内部的にプライベートな状態を自己呼び出し匿名関数内にカプセル化します。

2番目のアプローチは、プライベートメンバーをカプセル化するのに適していますが、インスタンス化可能なクラスにすることで、より「オブジェクト指向」にできます。

MyNamespace.MyClass = function() { ... };
MyNamespace.MyClass.prototype.someProperty = 'foo';

次に、「new」キーワードを使用してインスタンス化できます。

var aClass = new MyNamespace.MyClass();
aClass.init(...);
6
chrisf

名前空間を持つインスタンス化可能なクラスに次の構文を使用します

 var MYNamespace = MYNamespace|| {};

 MYNamespace.MyFirstClass = function (val) {
        this.value = val;
        this.getValue = function(){
                          return this.value;
                       };
    }

var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());

jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/

4
Razan Paul

使用しない理由

 return { methodName : methodDelegate}

2番目の例のように:

MyNamespace.MyClass = (function () {
    var someProperty = 5;

    var init = function () {
        //do something
    };

    return {
        someProperty: someProperty
        someFunction: someFunction
    };
}());

MyNamespace.MyClass.init();

名前空間を使用するときは、インスタンスではなく宣言について考える必要があります。

MyNamespace = {};
MyNamespace.sub = {};
MyNamespace.anotherSub = {};
MyNamespace.sub.MyClass = (function () {

    var static_var; //static private var

    var MyClass2 = function () {

        var privateVar; //private
        var privateFn = function () { }; //private 

        this.someProperty = 5;  //public
        this.anotherProperty = false;  //public
        this.someFunction = function () {  //public
            //do something
        };
    };

    return MyClass2;

})();
debugger;

var c1 = new MyNamespace.sub.MyClass();
c1.someProperty = 1; // creates 5->1.

var c2 = new MyNamespace.sub.MyClass();
c2.someProperty = 2;  // creates 5->2. c1 is still 1



debugger;
var myClass = function () {
    var someProperty = 5;
    var anotherProperty = false;

    var init = function () {
        //do something
    };

    var someFunction = function () {
        //do something
    };

    return {
        someProperty: someProperty,
        anotherProperty: anotherProperty,
        init: init,
        someFunction: someFunction
    };
};


MyNamespace.MyClass = myClass();
var c2 = MyNamespace.MyClass;
// how  are planning to create one more object, while it's a reference? copy      //the whole one?

c2.someProperty = 2; // changes 5 -> 2
var c3 = MyNamespace.MyClass.init(); // create 2 instead of 5

c3.someProperty = 3;    // changes c3 and c3 from 2 to 3.
console.log(c2.someProperty + c3.someProperty);

また、モジュールのアンチパターがどれほど人気が​​あったのか、ということもあります。宣言により、他の開発者が期待する方法で、異なるインスタンスで同じコードを使用することができます。コードの品質と読み取りの単純さが向上します。開発者の目標は、短いコードやD.R.Yではなく、読み取る単純なコードを書くことです。 -しかし、他の開発者が読んで理解するのは簡単です。最初にバグの数が減ります。 (c)S.マッコネル

1
Artem G

名前空間とクラス宣言を組み合わせる方法:

var ns = { // your namespace
    my_value: 1, // a value inside the namespace to avoid polluting
    MyClass: function() { // a class inside the namespace
        this.class_property: 12,
        this.class_method: function() {
            console.log("My property: " + this.class_property);
        }
    },
    myFunction: function() { // a function inside a namespace
        console.log("I can access namepsace value if you don't use 'new': " + this.my_value);
    }
};

あなたの価値へのアクセス:

console.log(ns.my_value);

さて、クラスと関数について:newを使用する場合、関数内のWord thisはそのコンストラクターを指します。 newを使用しない場合、thisは名前空間を指します。そう、

クラスの使用:

var obj = new ns.MyClass();

関数の使用:

ns.myFunction();

newを使用せずにオブジェクトを構築すると、thisは名前空間を指します。したがって、MyClass.class_propertyおよびMyClass.class_methodが追加されます。

1
marirena