39 votes

Questions orientées objet en Javascript

J'utilise javascript depuis un certain temps, mais je n'ai jamais appris le langage au-delà des bases. Je suis en train de lire "Pro Javascript Techniques" de John Resig. Je me pose des questions, mais je ne trouve pas les réponses dans le livre ou sur Google, etc.

John donne cet exemple dans son livre :
Fonction 1

function User( name, age ){
  this.name = name;
  this.age = age;
}
// Add a new function to the object prototype
User.prototype.getName = function(){
  return this.name;
};
User.prototype.getAge = function(){
  return this.age;
};
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());

Je suis toujours en train d'apprendre sur le prototype J'ai donc essayé d'écrire quelque chose de similaire :
Fonction n° 2

function User (name, age ) {
  this.name = name;
  this.age = age;
  this.getName = function() {
    return this.name;
  };
  this.getAge = function() {
    return this.age;
  };
}
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());

Il n'utilise pas le prototype pour créer les fonctions getName et getAge, mais le résultat est le même que dans l'exemple de John.

Je suis allé un peu plus loin, et j'ai créé ceci :
Fonction n° 3

var User = {
  name: "",
  age: 0,
  setName: function(name) {
    this.name = name;
  },
  setAge: function(age) {
    this.age = age;
  },
  getName: function() {
    return this.name;
  },
  getAge: function() {
    return this.age;
  }
};
User.setName("Bob");
User.setAge(44);
console.log("User: " + User.getName() + ", Age: " + User.getAge());

Encore une fois, l'apparence est différente de celle de l'exemple de John (et j'ai dû ajouter des méthodes setter), mais le résultat est le même.

Question n° 1 - quelle est la différence entre les 3 fonctions ? Quel est l'avantage de la propriété prototype, et la fonction n°2 fait-elle quelque chose d'incorrect, parce qu'il semble plus direct de coder la n°2 au lieu de la n° 1 (bien que je sois sûr que la n° 1 le fait mieux, vu que John l'a créée).

Question n°2 - Comment pourrais-je modifier la fonction n° 3 pour ne pas utiliser les méthodes setName et setAge, tout en conservant l'abréviation {...} ? L'abréviation {...} peut-elle avoir des constructeurs ?

Merci d'avance de m'aider à apprendre !

EDITAR Je pense que ma deuxième question était un peu confuse. Je voulais dire que je pouvais utiliser le raccourci {...} pour créer un objet Utilisateur, mais après avoir créé l'objet, dire quelque chose comme :

var user = new User("Bob", 44);

Comme dans la fonction 1 - ou est-ce impossible ?

EDIT #2 Wow ! Merci à tous pour ces réponses géniales. Cela rend les choses beaucoup plus claires pour moi. Donc, si je comprends bien, la différence entre le numéro 1 et le numéro 2 n'est pas trop importante. Si je ne crée qu'un seul objet "Utilisateur", ils ne sont probablement pas différents du tout. Mais si mon programme crée de nombreux objets "User", le n°1 sera probablement plus efficace et utilisera moins de mémoire puisque tous les objets partageront les mêmes fonctions.

J'apprécie vraiment toutes les bonnes réponses - Merci !

22voto

Glomek Points 12183

Chaque fois qu'une fonction() {} est évaluée, elle crée un nouvel objet fonction. Par conséquent, dans l'exemple #1, tous les objets User partagent les mêmes fonctions getName et getAge, mais dans les exemples #2 et #3, chaque objet possède sa propre copie de getName et getAge. Toutes les différentes fonctions getName se comportent exactement de la même manière, vous ne pouvez donc pas voir de différence dans le résultat.

L'abréviation {...} es un constructeur. Lorsqu'il est évalué, il construit un nouvel "objet" avec les propriétés données. Lorsque vous exécutez "new User(...)", il construit un nouvel "User". Il se trouve que vous avez créé un objet ayant le même comportement qu'un utilisateur, mais ils sont de types différents.

Réponse au commentaire :

Vous ne pouvez pas, directement. Vous pouvez créer une fonction qui crée un nouvel objet comme indiqué au point 3. Par exemple :

function make_user(name, age) {
    return {
        name: name,
        age: age,
        getName: function() { return name; },
        getAge: function() { return age; },
    };
}

var user = make_user("Joe", "18");

12voto

Bernard Points 729

Si vous voulez faire de la POO en JavaScript, je vous conseille vivement de vous renseigner sur les fermetures. J'ai commencé mon apprentissage sur le sujet avec ces trois pages web :

http://www.dustindiaz.com/javascript-private-public-privileged/

http://www.dustindiaz.com/namespace-your-javascript/

http://blog.morrisjohns.com/javascript_closures_for_dummies

Les différences entre 1, 2 et 3 sont les suivantes : 1) Est un exemple d'ajout de nouvelles méthodes à un objet existant. 2) Identique à l'exemple 1, sauf que certaines méthodes sont incluses dans l'objet dans la fonction Utilisateur. 3) C'est un exemple de définition d'un objet à l'aide de la fonction JSON . L'inconvénient est que vous ne pouvez pas utiliser new (du moins pas dans cet exemple) pour définir de nouvelles instances de cet objet. Cependant, vous bénéficiez du style de codage pratique de JSON.

Vous devriez absolument vous documenter sur JSON si vous ne le connaissez pas encore. JavaScript aura beaucoup plus de sens si vous comprenez JSON.

editar Si vous voulez utiliser new dans la fonction #3, vous pouvez l'écrire comme suit

function User() {
  return {
    name: "",
    age: 0,
    setName: function(name) {
      this.name = name;
    },
    setAge: function(age) {
      this.age = age;
    },
    getName: function() {
      return this.name;
    },
    getAge: function() {
      return this.age;
    }
  };
}

Bien sûr, toutes ces fonctions et propriétés seraient alors publiques. Pour les rendre privées, vous devez utiliser des fermetures. Par exemple, vous pouvez rendre l'âge et le nom privés avec cette syntaxe.

function User() {
  var age=0;
  var name="";
  return {
    setName: function(name_) {
      name = name_;
    },
    setAge: function(age_) {
      age = age_;
    },
    getName: function() {
      return name;
    },
    getAge: function() {
      return age;
    }
  };
}

5voto

Maiku Mori Points 4329

2 :

Vous pouvez accéder au nom et à l'âge, sans utiliser ces fonctions. En javascript, vous devez utiliser différentes astuces pour garder quelque chose de privé ou de protégé.

Este

User.name = "BoB";
User.age = 44;

produira le même résultat que votre exemple.

Il n'y a pas de constructeurs tels qu'ils apparaissent dans d'autres langues. Le plus simple serait de définir la fonction init() et de l'appeler juste après l'instance de l'objet.

Mais mon plus grand conseil pour vous est de regarder dans http://www.prototypejs.org/ . Il s'agit d'une bibliothèque javascript avec beaucoup de fonctionnalités intéressantes qui tente de rendre javascript "plus OO*".

En utilisant la bibliothèque de prototypes, vous pouvez faire en sorte que les classes se comportent davantage comme de vraies classes OOP. Elle comporte également des constructeurs.

Modifier : Pour ce qui est de la question que vous avez posée dans votre commentaire :

person = new User();
person.name = "Bob";
person.age = 44;

4voto

Paulo Lopes Points 1721

Votre exemple n°1 montre l'utilisation de la propriété prototype. Cette propriété est disponible pour tous les objets javascript que vous créez et vous permet d'ajouter des propriétés ou des fonctions à la déclaration de l'objet. Vous aviez donc un objet avec 2 propriétés et plus tard vous avez ajouté 4 fonctions (getters et setters).

Vous devriez voir la propriété prototype comme le moyen de modifier la spécification de votre objet au moment de l'exécution, disons que vous avez un objet appelé nom :

var Name = {
  First: "",
  Last: ""
};

Vous pouvez utiliser le prototype pour ajouter une fonction getFullName() plus tard, simplement :

Name.prototype.getFullName = function() { return this.First + " " + this.Last; }

Dans l'exemple 2, vous inlinez la déclaration de ces getters et setters dans la déclaration de l'objet, de sorte qu'au final, ils sont identiques. Enfin, dans le troisième exemple, vous utilisez la notation d'objet JavaScript. JSON .

Pour votre question 2, vous pouvez simplement déclarer votre objet comme :

var User = {
  name: "",
  age: 0
};

cela vous donnera le même objet sans getters et setters.

1voto

Jonathan Lonowski Points 45253

Question n° 1

prototype a l'avantage de singe Parcheando . Comme le montre le premier exemple, les fonctions sont ajoutées après coup. Vous pouvez continuer ainsi pour ajouter ou remplacer toutes les méthodes dont vous avez besoin (avec toutefois un avertissement).

Définir des objets comme le n°2 est plus conforme à la POO classique. Mais, là encore, le singe Parcheando n'est pas autorisé dans tous les langages POO.

Question n°2

Dans votre 3e fonction, vous n'avez même pas besoin de la fonction get y set fonctions -- name y age sont des propriétés publiques (l'inconvénient potentiel de {} ).

var User = {
  name: "",
  age: 0
};

User.name = 'Bob';
User.age = 44;

console.log("User: " + User.name + ", Age: " + User.age);

Lorsque vous créez un objet en utilisant {} (un objet littéral), {} est le constructeur (variant selon le navigateur). Mais, essentiellement, non, vous ne pouvez pas utiliser un constructeur dans ce format.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X