2014-04-17 3 views
5

Disons que j'ai le JSON suivant avec des objets person. Si j'analyse ceci, j'obtiendrai un tableau avec deux objets JavaScript. Disons que je veux équiper ces deux objets avec une méthode appelée introduction, qui fait quelque chose comme çaAttacher le prototype à l'objet JavaScript

function introduce() { 
    return "My name is " + this.name + " and I am " + this.age + " years old."; 
} 

Maintenant, je pouvais itérer sur mes deux personnes et appellent

person.constructor.prototype.introduce = introduce 

Cependant, cette exposera la fonction d'introduction dans TOUS les objets JavaScript, pas seulement les deux ci-dessus.

Je pourrais également attacher manuellement la fonction à chaque objet, mais si je veux étendre mon peuple avec des fonctions supplémentaires, je devrai itérer à nouveau sur toutes les personnes. Idéalement, je voudrais un prototype que je peux utiliser avec la méthode introduce et ensuite attacher ce prototype à tous mes gens, donc si j'étends plus tard le prototype, mes gens auront aussi des fonctions supplémentaires.

La question est: comment?

+1

juste faire 'person.prototype.introduce = introduire' et se débarrasser de la partie' constructor'. –

+1

pourquoi ne pas simplement faire une classe 'Person', parse json pour faire' Person'. N'importe quand ajouter une fonction au prototype 'Person'. – mshsayem

+0

@BrianGlaz: Je pense que 'person' est sa référence à l'objet lui-même, donc' person.prototype' n'existera pas. –

Répondre

3

Vous pouvez utiliser la propriété dépréciée__proto__ ou la méthode ES6 Object.setPrototypeOf. Notez qu'il est fortement déconseillé de muter le prototype d'un objet (c.f. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto), mais il semble être une utilisation légitime.

var you = { name: "Niels B." } 
you.__proto__ = { hello: function() { console.log(this.name) } } 
you.hello() 

Donc, pour votre problème spécifique:

function Person() {} 
Person.prototype = { 
    introduce: function() { 
    return "My name is " + this.name + " and I am " + this.age + " years old."; 
    } 
} 

Ensuite, pour chaque personne:

person.__proto__ = Person.prototype; 
// or 
Object.setPrototypeOf(person, Person.prototype); 

Voici une JSPerf pertinente: http://jsperf.com/parse-json-into-an-object-and-assign-a-prototype

fil connexes: https://groups.google.com/forum/#!topic/ringojs/PxS1O5jMx-8

+1

Cela ajoute la méthode à 'Object.prototype'. La question indique qu'il ne veut pas ajouter la méthode à tous les objets. –

+0

@cookiemonster assez sûr que non, il ne fait que muter le prototype de l'objet. – Aegis

+0

Le prototype de l'objet est 'Object.prototype'. http://jsfiddle.net/sdQwQ/ –

3

Je vous suggère de créer une classe:

JSBin

var Person = (function() { 
    function Person(person) { 
     this.person = person; 
     this.name = person.name; 
     this.age = person.age; 
    } 
    Person.prototype.introduce = function() { 
     return "My name is " + this.name + " and I am " + this.age + " years old."; 
    }; 
    return Person; 
})(); 
+0

Hey! Peut-être une question stupide, mais quelle est la raison de l'emballage dans un IIFE? – Aegis

+2

@Aegis Variables privées et méthodes! – Beterraba

3

vous êtes question est un peu floue à comprendre.Mais je pense que vous ne voulez pas que votre « personne » d'être un objet régulier, mais plutôt une personne distincte « classe: »

var Person = function(obj){ 
    this.name = obj.name; 
}; 

Person.prototype.introduce = function(){ 
    return console.log('hi, I\'m '+this.name); 
}; 

var personA = new Person({ name:'a' }); 
var personB = new Person({ name:'b' }); 

personA.introduce(); // "hi, I'm a" 
personB.introduce(); // "hi, I'm b" 
+1

Donc, la conclusion est qu'il n'est pas possible d'attribuer gracieusement des prototypes à des objets (littéraux) existants. Au lieu de cela, de nouveaux objets doivent être créés en utilisant une fonction constructeur. –

+0

@NielsB. Eh bien, bien que cela soit possible, vous ne voulez pas le faire, puisque vous ne voulez que '' introduire '' pour les objets _certain_, dans mon exemple une instance 'Person'. – rgthree

+0

Oui, je sais. Je ne veux pas remplacer le prototype pour TOUS les objets, mais il semble intuitivement plus efficace d'itérer sur un tableau et de remplacer la référence du prototype au lieu de créer un nouvel ensemble d'objets. –

3

Faire une simple classe Person:

function Person(name,age){ 
    this.name = name; 
    this.age = age 
} 

Dites, vous ont ce tableau:

var people = [ 
    { 
    "name": "Alice", 
    "age": 28, 
    }, 
    { 
    "name": "Bob", 
    "age": 33 
    } 
]; 

Convertir people-Person tableau:

people = people.map(function(p){ 
    return new Person(p.name,p.age) 
}); 

Ajouter la méthode prototype:

Person.prototype.introduce = introduce 
2

Créer une classe personne et utiliser Person.prototype:

function Person(name, age){ 
    this.name = name; 
    this.age= age; 
} 

function introduce() { 
    return "My name is " + this.name + " and I am " + this.age + " years old."; 
} 

Person.prototype.introduce = introduce; 

p1 = new Person ("bob", 33); 
p1.introduce(); 
1

je suggère la création d'une structure pour ces personnes.

var Person = function Person(init){ 
this.name = init.name; 
this.age = init.age; 
}; 
Person.constructor = Person; 

Ensuite, itérer pour construire les gens.

var people = []; 
for(var i = 0; i < yourJson.length; i++){ 
people.push(new Person(yourJson[i])); 
} 

Maintenant que les gens sont construits, vous voudrez peut-être leur permettre de se présenter. Vous pouvez simplement étendre votre "classe" Person (définition).

Person.prototype.introduce = function() { 
    return "My name is " + this.name + " and I am " + age + " years old."; 
} 

qui leur permettra d'utiliser cette fonction

for(var i = 0; i < people.length; i++){ 
console.log(people[i].introduce()); 
} 
1

Si vous ne voulez pas re construire chaque fois que vous pouvez essayer ceci:

var people =[ 
    { 
    "name": "Alice", 
    "age": 28, 
    }, 
    { 
    "name": "Bob", 
    "age": 33 
    } 
], 
i=-1,len=people.length,tmp 
,proto={ 
    sayName: function(){ 
    console.log("from sayname",this.data.name); 
    } 
}; 
while(++i<len){ 
    tmp=Object.create(proto); 
    tmp.data=people[i]; 
    people[i]=tmp; 
} 
people[0].sayName(); 
proto.sayName=function(){console.log("changed it");}; 
people[1].sayName(); 

Si vos objets JSON ont Beaucoup de membres alors cela pourrait vous éviter d'avoir à les copier dans votre fonction de constructeur, mais je ne suis pas sûr si vous obtenez plus de performance à partir de lui.