如何正确设置 JavaScript 命名空间和类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11651527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:40:13  来源:igfitidea点击:

How to set up JavaScript namespace and classes properly?

javascriptoopjavascript-frameworkjavascript-objectsjavascript-namespaces

提问by TruMan1

It seems there are so many ways to set up a JavaScript application so it is confusing as to which one is correct or best. Are there any difference to the below techniques or a better way of doing this?

似乎有很多方法可以设置 JavaScript 应用程序,因此对于哪一种是正确的或最好的方法感到困惑。以下技术或更好的方法有什么区别吗?

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

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

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

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

Another way:

其它的办法:

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();

The first technique feelsmore like a class. I am coming from server-side background if this makes a difference. The second technique seems more redundant and a bit awkward, but I see this used a lot too. Can someone please help shed some light and advise the best way to move forward? I want to create a application with lots of classes talking to each other.

第一种技术感觉更像是一堂课。如果这有所作为,我来自服务器端背景。第二种技术似乎更多余,也有点笨拙,但我看到它也经常使用。有人可以帮助阐明并建议前进的最佳方式吗?我想创建一个应用程序,其中包含许多相互通信的类。

回答by Naftali aka Neal

Do neither of those things.

这两件事都不要做。

Make a javascript "class":

制作一个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();


One with static vars:

一种带有静态变量的:

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();


With a "constructor" (all of the examples have a "constructor", this one just has parameters to work with):

使用“构造函数”(所有示例都有一个“构造函数”,这个只有参数可以使用):

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);


With all of the above you can do:

有了以上所有内容,您可以执行以下操作

MyNamespace.MyClass.someFunction();

But you cannot do(from the outside):

但是你不能做(从外面):

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

回答by chrisf

The first example is simply an Object literal- it cannot be instantiated and doesn't have private members. The second example has some incorrect syntax (var someProperty: 5should be var someProperty = 5) but is using a closure to encapsulate internal private state within a self-invoking anonymous function.

第一个例子只是一个对象字面量——它不能被实例化,也没有私有成员。第二个例子有一些不正确的语法(var someProperty: 5应该是var someProperty = 5),但使用闭包将内部私有状态封装在自调用匿名函数中。

The second approach looks better for encapsulating private members, but could be made more "Object-oriented" by making it an instantiable class:

第二种方法看起来更适合封装私有成员,但可以通过使其成为可实例化的类来使其更加“面向对象”:

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

Then you can instantiate it with the 'new' keyword:

然后你可以用 'new' 关键字实例化它:

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

回答by Razan Paul

I use the following syntax for the instantiable classes with namespace

我对具有命名空间的可实例化类使用以下语法

 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/

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

回答by Artem G

Why you should never use

为什么你永远不应该使用

 return { methodName : methodDelegate}

like in second example:

就像在第二个例子中:

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

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

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

MyNamespace.MyClass.init();

When you use namespace you have to think about it as about declaration, not the instance.

当您使用命名空间时,您必须将其视为声明,而不是实例。

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);

And no metter how much Module anti-patter was popular. Declaration gives you an ability to use the same code with different instances in an expected way for other developers . The quality of code and simplicity of its reading increases. The goal of any developer is to write a simple code to be read, not a shorter or D.R.Y. - but simple to be read and be understanded by another developer. That decreases the number of bugs first. (c) S. McConnell

并且不知道模块反模式流行了多少。声明使您能够以其他开发人员预期的方式将相同的代码用于不同的实例。代码的质量和阅读的简单性都会增加。任何开发人员的目标都是编写易于阅读的简单代码,而不是较短或枯燥的代码——而是易于其他开发人员阅读和理解的代码。这首先减少了错误的数量。(c) S.麦康奈尔

回答by marirena

How to combine namespace and class declaration:

如何结合命名空间和类声明:

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);
    }
};

Accessing your value:

访问您的价值:

console.log(ns.my_value);

Now, for the Class and Function: If you use new, the word thisinside the function will point to it's constructor. If you don't use new, thiswill point to the namespace. So,

现在,对于类和函数:如果使用newthis函数内的单词将指向它的构造函数。如果不使用new,this将指向命名空间。所以,

Using a Class:

使用类:

var obj = new ns.MyClass();

Using the Function:

使用功能:

ns.myFunction();

If you construct the object without new, thiswill point to the namespace, so the namespace will be "destroyed" because MyClass.class_propertyand MyClass.class_methodwill be added to it.

如果你构造的对象没有new,this将指向命名空间,所以命名空间将被“破坏”,因为MyClass.class_property并且MyClass.class_method将被添加到它。