Как правильно настроить пространство имен и классы 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();
Первый метод больше похож на класс. Я исхожу из серверного фона, если это имеет значение. Второй метод кажется более избыточным и немного неудобным, но я вижу, что это слишком много. Может кто-то, пожалуйста, поможет пролить свет и посоветовать лучший способ двигаться вперед? Я хочу создать приложение с большим количеством классов, разговаривающих друг с другом.
Ответы
Ответ 1
Не делайте ни одной из этих вещей.
Сделайте javascript "class":
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();
Один со статическими 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();
С "конструктором" (все примеры имеют "конструктор", у этого только есть параметры для работы):
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!
Ответ 2
Первый пример - это просто литерал объекта - он не может быть создан и не имеет частных членов. Второй пример имеет некорректный синтаксис (var someProperty: 5
должен быть var someProperty = 5
), но использует закрытие для инкапсуляции внутреннего частного состояния в самозапускающуюся анонимную функцию.
Второй подход выглядит лучше для инкапсуляции частных членов, но его можно сделать более "Объектно-ориентированным", сделав его понятным классом:
MyNamespace.MyClass = function() { ... };
MyNamespace.MyClass.prototype.someProperty = 'foo';
Затем вы можете создать экземпляр с помощью ключевого слова 'new':
var aClass = new MyNamespace.MyClass();
aClass.init(...);
Ответ 3
Я использую следующий синтаксис для реализуемых классов с пространством имен
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
Почему вы никогда не должны использовать
return { methodName : methodDelegate}
как во втором примере:
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 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);
И не важно, насколько популярна система Anti-Patter. Декларация дает вам возможность использовать один и тот же код с разными экземплярами ожидаемым способом для других разработчиков. Качество кода и простота его чтения увеличивается. Цель любого разработчика - написать простой код для чтения, а не более короткий или D.R.Y. - но просты для чтения и понимания другим разработчиком. Это уменьшает количество ошибок в первую очередь. (c) С. Макконнелл
Ответ 5
Как объединить пространство имен и объявление класса:
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
, слово this
внутри функции укажет на конструктор. Если вы не используете new
, this
укажет на пространство имен. Таким образом,
Использование класса:
var obj = new ns.MyClass();
Использование функции:
ns.myFunction();
Если вы создадите объект без new
, this
укажет на пространство имен, поэтому пространство имен будет "уничтожено", потому что к нему будут добавлены MyClass.class_property
и MyClass.class_method
.