2009-01-14 4 views
39

J'utilise javascript depuis un moment, mais je n'ai jamais appris la langue après les bases. Je suis en train de lire "Pro Javascript Techniques" de John Resig - je suis en train de poser quelques questions, mais je ne trouve pas les réponses dans le livre ou sur google, etc.Questions orientées objet en Javascript

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 encore à apprendre sur la propriété prototype, donc j'essayé d'écrire quelque chose de similaire:
Fonction # 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 propriété prototype pour créer les fonctions getName et getAge, mais la sortie est le même que l'exemple de John.

je l'ai pris un peu plus loin, et a créé ceci:
Fonction # 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 - il semble différent de l'exemple de John (et je devais ajouter des méthodes setter), mais la sortie est le même.

Question # 1 - Quelle est la différence entre les 3 fonctions? Quel est l'avantage de la propriété du prototype, et la fonction # 2 fait quelque chose de mal, parce qu'elle semble plus directe au code # 2 au lieu de # 1 (bien que je suis sûr que # 1 le fait mieux que John l'a créé) .

Question # 2 - Comment est-ce que je pourrais modifier la fonction # 3 pour ne pas utiliser les méthodes setName et setAge, tout en gardant le {...} raccourci? Est-ce que le raccourci {...} peut avoir des constructeurs?

Merci d'avance de m'avoir aidé à apprendre!

EDIT Je pense que ma deuxième question était un peu confuse. Je voulais dire comment pourrais-je 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); 

Tout comme dans la fonction # 1 - ou est-ce pas possible ?

EDIT # 2 Wow! Merci à tous pour les réponses impressionnantes. Cela me rend vraiment beaucoup plus clair. Donc, si je comprends bien, la différence entre # 1 et # 2 ne sont pas trop. 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 Utilisateur, le # 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!

Répondre

22

Chaque fois qu'une fonction() {} est évaluée, elle crée un nouvel objet fonction. Par conséquent, dans # 1, tous les objets Utilisateur partagent les mêmes fonctions getName et getAge, mais dans # 2 et # 3, chaque objet possède sa propre copie de getName et getAge.Toutes les différentes fonctions getName se comportent toutes exactement de la même manière, de sorte que vous ne voyez aucune différence dans la sortie.

Le raccourci {0} est un constructeur. Lorsqu'elle est évaluée, elle construit un nouvel "objet" avec les propriétés données. Lorsque vous exécutez "new User (...)", il construit un nouveau "User". Vous avez créé un objet avec 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 selon # 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"); 
+0

Je suppose que je veux dire la question 2 est comment puis-je modifier la fonction # 3 pour que je puisse dire quelque chose comme personne var = new User(); – BrianH

+0

Ce commentaire n'est pas tout à fait vrai "Toutes les différentes fonctions de getName se comportent toutes exactement de la même manière". Le type # 2 a accès à des vars privés – meouw

+0

Mon point était qu'ils se comportent de la même manière dans l'exemple. – Glomek

5

2:

Vous pouvez accéder au nom et à l'âge, sans utiliser de telles fonctions. En JavaScript, vous devez utiliser différents hacks pour garder quelque chose de privé ou protégé.

Ce

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

produira même sortie que votre exemple.

Aucun constructeur n'apparaît dans les autres langues. Le plus simple serait de simplement définir la fonction init() et de l'appeler juste après l'instance de l'objet.

Mais ma plus grande astuce pour vous est de regarder dans http://www.prototypejs.org/. C'est une bibliothèque javascript avec beaucoup de fonctionnalités intéressantes qui essaie de rendre javascript "plus d'OO *". En utilisant une bibliothèque de prototypes, vous pouvez faire en sorte que les classes se comportent davantage comme de véritables classes OOP. Il comporte également des constructeurs.

Edit: Quant à ce que vous avez demandé à votre commentaire:

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

Question # 1

prototype a l'avantage de monkey patching. Comme le montre le premier exemple, les fonctions sont ajoutées après le fait. Vous pouvez continuer à ajouter ou remplacer toutes les méthodes dont vous avez besoin (avec un avertissement correct).

La définition d'objets comme le n ° 2 est plus conforme aux OOP classiques. Mais, encore une fois, le patch de singe n'est pas autorisé dans toutes les langues OOP.

Question # 2

Dans votre 3ème fonction, vous ne même pas besoin des get et set fonctions - name et age sont des propriétés publiques (le potentiel de baisse {}).

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 à l'aide {} (un littéral d'objet), {} est le constructeur (variable sur le navigateur). Mais, essentiellement, vous ne pouvez pas utiliser un constructeur dans ce format.

+0

L'ajout d'une propriété ou d'une méthode à un objet défini par l'utilisateur n'est pas considéré comme un correctif de singe. La correction de singe consiste à ajouter des méthodes ou des propriétés aux objets intégrés, c'est-à-dire à modifier le comportement du langage lui-même. – meouw

4

Votre exemple # 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 d'objet, vous avez 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 la façon de modifier vos spécifications d'objet lors de l'exécution, que vous avez un objet appelé nom:

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

Vous pouvez utiliser le prototype d'ajouter une getFullName fonction() plus tard simplement:

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

dans l'exemple 2 vous en ligne la déclaration de ces accesseurs dans la déclaration d'objet alors à la fin ce sont les mêmes. Enfin sur le 3ème exemple vous utilisez la notation d'objet JavaScript, vous devriez voir JSON.

À propos de votre question 2, vous pouvez simplement déclarer votre objet comme:

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

cela vous donnera le même objet sans accesseurs.

12

Si vous voulez faire de la POO en JavaScript, je suggère fortement de rechercher des fermetures. J'ai commencé mon apprentissage sur le sujet avec ces trois pages:

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-ce un exemple d'ajout de nouvelles méthodes à un objet existant. 2) Est identique à # 1 sauf que certaines méthodes sont incluses dans l'objet dans la fonction Utilisateur. 3) Est un exemple de définition d'un objet en utilisant JSON. Le défaut est que vous ne pouvez pas utiliser new (du moins pas avec cet exemple) pour définir de nouvelles instances de cet objet. Cependant, vous bénéficiez du style de codage JSON pratique.

Vous devriez certainement lire sur JSON si vous ne le connaissez pas encore. JavaScript aura beaucoup plus de sens lorsque vous comprendrez JSON.

modifier Si vous souhaitez utiliser les nouvelles dans la fonction # 3, vous pouvez l'écrire comme

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 public. Pour les rendre privés, 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; 
    } 
    }; 
} 
+1

Merci pour cela ... j'espère que vous êtes toujours là et répondre à des choses sur SO :) –

Questions connexes