Constructeurs dans les objets JavaScript


Answers

Voici un modèle que j'utilise parfois pour un comportement similaire à celui de la POO en JavaScript. Comme vous pouvez le voir, vous pouvez simuler des membres privés (à la fois statiques et instances) en utilisant des fermetures. Ce que new MyClass() retournera est un objet avec seulement les propriétés assignées à this objet et à l'objet prototype 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;
})();

On m'a demandé de l'héritage en utilisant ce modèle, alors voici:

// 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 pour tout utiliser:

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 interagissent correctement les unes avec les autres (elles partagent l'identifiant statique de MyClass , la méthode announce utilise la bonne méthode get_name , etc.)

Une chose à noter est le besoin d'observer les propriétés de l'instance. Vous pouvez réellement faire passer la fonction hasOwnProperty travers toutes les propriétés d'instance (en utilisant hasOwnProperty ) qui sont des fonctions, et ajouter super_<method name> une super_<method name> . Cela vous permet d'appeler this.super_get_name() au lieu de le stocker dans une valeur temporaire et de l'appeler en utilisant call .

Pour les méthodes sur le prototype, vous n'avez pas à vous soucier de ce qui précède, si vous voulez accéder aux méthodes de prototype de la super classe, vous pouvez simplement appeler this.constructor.super.prototype.methodName . Si vous voulez le rendre moins verbeux, vous pouvez bien sûr ajouter des propriétés de commodité. :)

Question

Les classes / objets JavaScript peuvent-ils avoir des constructeurs? Comment sont-ils créés?




C'est un constructeur:

function MyClass() {}

Quand tu fais

var myObj = new MyClass();

MyClass est exécutée et un nouvel objet est retourné de cette classe.




http://www.jsoops.net/ est assez bon pour oop dans Js. Si fournir privé, protégé, variable publique et la fonction, et également la fonction d'héritage. Exemple de code:

var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public

    pri.className = "I am A ";

    this.init = function (var1)// constructor
    {
        pri.className += var1;
    }

    pub.getData = function ()
    {
        return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
        + ", ID=" + pro.getClassId() + ")";
    }

    pri.getClassName = function () { return pri.className; }
    pro.getClassName = function () { return pri.className; }
    pro.getClassId = function () { return 1; }
});

var newA = new ClassA("Class");

//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)

//***You can not access constructor, private and protected function
console.log(typeof (newA.init));            // undefined
console.log(typeof (newA.className));       // undefined
console.log(typeof (newA.pro));             // undefined
console.log(typeof (newA.getClassName));    // undefined



Ils le font si vous utilisez Typescript - open source de MicroSoft :-)

class BankAccount {
 balance: number;
 constructor(initially: number) {
 this.balance = initially;
 }
 deposit(credit: number) {
 this.balance += credit;
 return this.balance;
 }
}

Typescript vous permet de «simuler» des constructions OO qui sont compilées dans des constructions javascript. Si vous démarrez un grand projet, cela peut vous faire gagner beaucoup de temps et atteindre la version de la version 1.0.

http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf

Le code ci-dessus est «compilé» pour:

var BankAccount = (function () {
    function BankAccount(initially) {
        this.balance = initially;
    }
    BankAccount.prototype.deposit = function (credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();



En JavaScript, le type d'appel définit le comportement de la fonction:

  • Appel direct func()
  • Invocation de méthode sur un objet obj.func()
  • Invocation de constructeur new func()
  • Invocation indirecte func.call() ou func.apply()

La fonction est invoquée en tant que constructeur lors de l'appel en utilisant un new opérateur:

function Cat(name) {
   this.name = name;
}
Cat.prototype.getName = function() {
   return this.name;
}

var myCat = new Cat('Sweet'); // Cat function invoked as a constructor

Toute instance ou objet prototype en JavaScript a un constructor propriété, qui fait référence à la fonction constructeur.

Cat.prototype.constructor === Cat // => true
myCat.constructor         === Cat // => true

Vérifiez ce post sur la propriété constructeur.




Je suppose que je vais poster ce que je fais avec la fermeture de javascript puisque personne n'utilise encore la fermeture.

var user = function(id) {
  // private properties & methods goes here.
  var someValue;
  function doSomething(data) {
    someValue = data;
  };

  // constructor goes here.
  if (!id) return null;

  // public properties & methods goes here.
  return {
    id: id,
    method: function(params) {
      doSomething(params);
    }
  };
};

Les commentaires et suggestions pour cette solution sont les bienvenus. :)




Ici, nous devons remarquer un point dans le script java, c'est un langage sans classe cependant, nous pouvons l'atteindre en utilisant des fonctions dans le script java. La façon la plus courante d'y parvenir est de créer une fonction dans le script java et d'utiliser un nouveau mot-clé pour créer un objet et utiliser ce mot - clé pour définir la propriété et les méthodes.Below est l'exemple.

// Function constructor

   var calculator=function(num1 ,num2){
   this.name="This is function constructor";
   this.mulFunc=function(){
      return num1*num2
   };

};

var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call

//Constructors With Prototypes

var calculator=function(){
   this.name="Constructors With Prototypes";
};

calculator.prototype.mulFunc=function(num1 ,num2){
 return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call



Ce modèle m'a bien servi. Avec ce modèle, vous créez des classes dans des fichiers séparés, chargez-les dans votre application globale "au besoin".

// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};

// "Package" 
// Similar to how you would establish a package in other languages
(function() {

// "Class"
var MyClass = function(params) {
    this.initialize(params);
}

    // "Private Static" vars 
    //    - Only accessible to functions in this class.
    //    - Doesn't get wiped out when we create a new instance.
    var countInstances = 0;
    var allInstances = [];

    // "Private Static" functions 
    //    - Same as above, but it's a function accessible 
    //      only to other functions in this class.
    function doSomething(){
    }

    // "Public Static" vars
    //    - Everyone has access.
    //    - Doesn't get wiped out when we create a new instance.
    MyClass.counter = 0;

    // "Public Static" functions
    //    - Same as above, but anyone can call this "static method".
    //    - Kinda like a singleton class situation.
    MyClass.foobar = function(){
    }

    // Public properties and methods are built into the "prototype"
    //    - This is how each instance can become unique unto itself.
    //    - Establishing "p" as "local" (Static Private) variable 
    //      simply so we don't have to keep typing "MyClass.prototype" 
    //      for each property and function.
var p = MyClass.prototype;

    // "Public" vars
    p.id = null;
    p.firstname = null;
    p.lastname = null;

    // "Private" vars
    //    - Only used by "this" instance.
    //    - There isn't "true" privacy for each 
    //      instance so we have to fake it. 
    //    - By tradition, we indicate "privacy"  
    //      by prefixing it with an underscore. 
    //    - So technically, anyone can access, but we simply 
    //      don't tell anyone about it (e.g. in your API)
    //      so no one knows about it :)
    p._foo = null;

    p.initialize = function(params){
        this.id = MyClass.counter++;
        this.firstname = params.firstname;
        this.lastname = params.lastname;
        MyClass.counter++;
        countInstances++;
        allInstances.push(this);
    }

    p.doAlert = function(theMessage){
        alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ".  Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
    }


// Assign class to app
myApp.MyClass = MyClass;

// Close the "Package"
}());

// Usage example:
var bob = new myApp.MyClass({   firstname   :   "bob",
                                lastname    :   "er"
                            });

bob.doAlert("hello there");



Alors, quel est le point de la propriété "constructeur"? Vous ne pouvez pas savoir où cela pourrait être utile, des idées?

Le point de la propriété constructeur est de fournir un moyen de prétendre que JavaScript a des classes. Une des choses que vous ne pouvez pas faire est de changer le constructeur d'un objet après sa création. C'est compliqué.

J'ai écrit un article assez complet il y a quelques années: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html