Peut-classes JavaScript/objets possèdent des constructeurs? Comment sont-ils créés?
Réponses
Trop de publicités?À l'aide de prototypes:
function Box(color) // Constructor
{
this.color = color;
}
Box.prototype.getColor = function()
{
return this.color;
}
Se cacher "de la couleur" (ressemble un peu à une variable membre privée):
function Box(col)
{
var color = col;
this.getColor = function()
{
return color;
}
}
Utilisation:
var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue
var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green
Voici un modèle que j'ai parfois l'utilisation de la programmation orientée objet-un comportement similaire en JavaScript. Comme vous pouvez le voir, vous pouvez simuler privé (en statique et en instance) les membres à l'aide de fermetures. Ce new MyClass()
sera de retour est un objet avec les propriétés attribuées à l' this
objet et dans l' prototype
objet de la "classe".
var MyClass = (function () {
// private static
var nextId = 1;
// constructor
var cls = function () {
// private
var id = nextId++;
var name = 'Unknown';
// public (this instance only)
this.get_id = function () { return id; };
this.get_name = function () { return name; };
this.set_name = function (value) {
if (typeof value != 'string')
throw 'Name must be a string';
if (value.length < 2 || value.length > 20)
throw 'Name must be 2-20 characters long.';
name = value;
};
};
// public static
cls.get_nextId = function () {
return nextId;
};
// public (shared across instances)
cls.prototype = {
announce: function () {
alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
}
};
return cls;
})();
J'ai demandé à propos de l'héritage à l'aide de ce modèle, donc voilà:
// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
// We use an intermediary empty constructor to create an
// inheritance chain, because using the super class' constructor
// might have side effects.
var construct = function () {};
construct.prototype = superCls.prototype;
cls.prototype = new construct;
cls.prototype.constructor = cls;
cls.super = superCls;
}
var MyChildClass = (function () {
// constructor
var cls = function (surName) {
// Call super constructor on this instance (any arguments
// to the constructor would go after "this" in call(…)).
this.constructor.super.call(this);
// Shadowing instance properties is a little bit less
// intuitive, but can be done:
var getName = this.get_name;
// public (this instance only)
this.get_name = function () {
return getName.call(this) + ' ' + surName;
};
};
inherit(cls, MyClass); // <-- important!
return cls;
})();
Et un exemple à ça:
var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"
var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"
alert(john instanceof MyClass); // true
Comme vous pouvez le voir, les classes correctement interagir les uns avec les autres (ils partagent la statique id d' MyClass
, announce
méthode utilise le bon get_name
méthode, etc.)
Une chose à noter est la nécessité de l'ombre des propriétés d'une instance. Vous pouvez réellement faire de l' inherit
de la fonction aller à travers toutes les propriétés de l'occurrence (à l'aide d' hasOwnProperty
) qui sont des fonctions, et d'automatiquement ajouter un super_<method name>
de la propriété. Ce serait vous appelez this.super_get_name()
, au lieu de les stocker dans une valeur temporaire et l'appel lié à l'aide de call
.
Pour les méthodes sur le prototype que vous n'avez pas besoin de s'inquiéter à ce sujet, cependant, si vous souhaitez accéder à la super-classe de " prototype méthodes, vous pouvez les appeler this.constructor.super.prototype.methodName
. Si vous voulez la rendre moins verbeux vous pouvez bien sûr ajouter la commodité des propriétés. :)
Il me semble que la plupart de vous donner l'exemple de getters et setters pas un constructeur, c'est à dire http://en.wikipedia.org/wiki/Constructor_(objet oriented_programming).
déjeuné-dan était plus proche, mais l'exemple ne fonctionne pas dans jsFiddle.
Cet exemple crée un constructeur privé de la fonction qui ne fonctionne que lors de la création de l'objet.
var color = 'black';
function Box()
{
// private property
var color = '';
// private constructor
var __construct = function() {
alert("Object Created.");
color = 'green';
}()
// getter
this.getColor = function() {
return color;
}
// setter
this.setColor = function(data) {
color = data;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Si vous voulais attribuer des propriétés publiques, alors que le constructeur pourrait être défini comme tel:
var color = 'black';
function Box()
{
// public property
this.color = '';
// private constructor
var __construct = function(that) {
alert("Object Created.");
that.color = 'green';
}(this)
// getter
this.getColor = function() {
return this.color;
}
// setter
this.setColor = function(color) {
this.color = color;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Quel est donc le point de "constructeur" propriété? Ne peut pas comprendre d'où il etre utile, des idées?
Le point de la propriété constructeur est de fournir un moyen de faire semblant de JavaScript a des classes. Une des choses que vous ne peut utilement faire est de changer un constructeur de l'objet après qu'il a été créé. C'est compliqué.
J'ai écrit un assez complet sur elle il y a quelques années: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
Exemple ici: http://jsfiddle.net/FZ5nC/
Essayez ce modèle:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
v1: null
,v2: null
,f1: function Name_Space_ClassName_f1(){}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;
//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>
Vous devez ajuster votre espace de noms si vous êtes à la définition d'une classe statique:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>
Exemple de classe:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
this.Width = width;
this.Height = height;
this.Color = color;
}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
Width: null
,Height: null
,Color: null
,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
var canvas = document.getElementById(canvasId);
var context = canvas.getContext("2d");
context.fillStyle = this.Color;
context.fillRect(x, y, this.Width, this.Height);
}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;
//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
return new Shape.Rectangle(50,25,'#ff0000');
}
</script>
Exemple d'instanciation:
<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");
var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);
var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);
Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>
Avis de fonctions sont définies comme A. B = fonction A_B(). C'est pour rendre votre script plus facile à déboguer. Ouvrez google Chrome, Inspecter l'Élément du panneau, l'exécution de ce script, et d'élargir la trace de débogage:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};
//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
A.Func.That.Does.Not.Exist();
}
Fail.Test();
</script>