Il semble qu'il existe de nombreuses façons de configurer une application JavaScript, il est donc difficile de savoir laquelle est correcte ou la meilleure. Y a-t-il une différence entre les techniques ci-dessous ou une meilleure façon de procéder?
MyNamespace.MyClass = {
someProperty: 5,
anotherProperty: false,
init: function () {
//do initialization
},
someFunction: function () {
//do something
}
};
$(function () {
MyNamespace.MyClass.init();
});
Autrement:
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();
La première technique se sent plus comme une classe. Je viens de l'arrière-plan côté serveur si cela fait une différence. La deuxième technique semble plus redondante et un peu gênante, mais je vois que cela est également très utilisé. Quelqu'un peut-il aider à faire la lumière et à vous conseiller sur la meilleure façon d'avancer? Je veux créer une application avec beaucoup de classes qui se parlent.
Ne faites rien de tout cela.
Créez une "classe" 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();
Un avec vars statiques:
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();
Avec un "constructeur" (tous les exemples ont un "constructeur", celui-ci a juste des paramètres avec lesquels travailler):
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);
Avec tout ce qui précède, vous pouvez le faire:
MyNamespace.MyClass.someFunction();
Mais vous ne pouvez pas faire (de l'extérieur):
MyNamespace.MyClass.privateFn(); //ERROR!
Le premier exemple est simplement un Object literal - il ne peut pas être instancié et n'a pas de membres privés. Le deuxième exemple a une syntaxe incorrecte (var someProperty: 5
devrait être var someProperty = 5
) mais utilise une fermeture pour encapsuler l'état privé interne dans une fonction anonyme auto-invoquante.
La seconde approche semble meilleure pour encapsuler des membres privés, mais pourrait être rendue plus "orientée objet" en en faisant une classe instanciable:
MyNamespace.MyClass = function() { ... };
MyNamespace.MyClass.prototype.someProperty = 'foo';
Ensuite, vous pouvez l'instancier avec le "nouveau" mot clé:
var aClass = new MyNamespace.MyClass();
aClass.init(...);
J'utilise la syntaxe suivante pour les classes instanciables avec 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/
Pourquoi vous ne devriez jamais utiliser
return { methodName : methodDelegate}
comme dans le deuxième exemple:
MyNamespace.MyClass = (function () {
var someProperty = 5;
var init = function () {
//do something
};
return {
someProperty: someProperty
someFunction: someFunction
};
}());
MyNamespace.MyClass.init();
Lorsque vous utilisez un espace de noms, vous devez le considérer comme une déclaration, et non l'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);
Et aucun compteur combien le module anti-patter était populaire. La déclaration vous donne la possibilité d'utiliser le même code avec différentes instances d'une manière attendue pour d'autres développeurs. La qualité du code et la simplicité de sa lecture augmentent. Le but de tout développeur est d'écrire un code simple à lire, pas un code plus court ou D.R.Y. - mais simple à lire et à comprendre par un autre développeur. Cela diminue d'abord le nombre de bogues. c) S. McConnell
Comment combiner espace de noms et déclaration de classe:
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);
}
};
Accéder à votre valeur:
console.log(ns.my_value);
Maintenant, pour la classe et la fonction: Si vous utilisez new
, le mot this
à l'intérieur de la fonction pointera vers son constructeur. Si vous n'utilisez pas new
, this
pointera vers l'espace de noms. Donc,
Utilisation d'une classe:
var obj = new ns.MyClass();
Utilisation de la fonction:
ns.myFunction();
Si vous construisez l'objet sans new
, this
pointera vers l'espace de noms, donc l'espace de noms sera "détruit" car MyClass.class_property
et MyClass.class_method
y sera ajouté.