2014-04-17 16 views
5

Diciamo che ho il seguente JSON con oggetti personali.Allegare il prototipo all'oggetto JavaScript

[ 
    { 
    "name": "Alice", 
    "age": 28, 
    }, 
    { 
    "name": "Bob", 
    "age": 33 
    } 
] 

Se analizzo questo, otterrò un array con due oggetti JavaScript. Diciamo, voglio dotare questi due oggetti con un metodo chiamato introdurre, che fa qualcosa di simile

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

Ora, ho potuto iterare i miei due persone e chiamare

person.constructor.prototype.introduce = introduce 

Tuttavia, questo esporterà la funzione di introduzione in TUTTI gli oggetti JavaScript, non solo i due sopra.

Potrei anche collegare manualmente la funzione a ciascun oggetto, ma se voglio estendere il mio personale con funzioni aggiuntive, dovrò ripetere tutte le persone nuovamente.

Idealmente, mi piacerebbe un prototipo che io possa adattare con il metodo introduce e quindi collegare questo prototipo a tutte le mie persone, quindi se in seguito estenderò il prototipo, il mio personale otterrà anche altre funzioni.

La domanda è: come?

+1

basta fare 'person.prototype.introduce = introduce' e sbarazzarsi della parte' constructor'. –

+1

perché non creare una classe 'Person', analizzare json per rendere' Person'. Ogni volta aggiungi una funzione al prototipo 'Person'. – mshsayem

+0

@BrianGlaz: Penso che 'person' sia il suo riferimento all'oggetto stesso, quindi' person.prototype' non esisterà. –

risposta

3

È possibile utilizzare lo deprecato__proto__ proprietà o il metodo ES6 Object.setPrototypeOf. Si noti che è fortemente sconsigliato per modificare il prototipo di un oggetto (c.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) ma sembra essere un caso legittimo.

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

Quindi per la vostra problema specifico:

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

Poi per ogni persona:

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

Ecco un JSPerf rilevante: http://jsperf.com/parse-json-into-an-object-and-assign-a-prototype

filo Correlati: https://groups.google.com/forum/#!topic/ringojs/PxS1O5jMx-8

+1

Questo aggiunge il metodo a 'Object.prototype'. La domanda afferma che non vuole aggiungere il metodo a tutti gli oggetti. –

+0

@cookiemonster abbastanza sicuro che non lo fa, si modifica solo il prototipo dell'oggetto. – Aegis

+0

Il prototipo dell'oggetto è 'Object.prototype'. http://jsfiddle.net/sdQwQ/ –

3

suggerisco di creare una 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

Ehi! Potrebbe essere una domanda sciocca, ma qual è la ragione per avvolgere questo in un IIFE? – Aegis

+2

@Aegis Variabili e metodi privati! – Beterraba

3

Sei la questione è un po 'confuso per capire.Ma penso che non si desidera che il "persona" ad essere un oggetto regolare, ma piuttosto una persona "di classe:" separato

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

Quindi sostanzialmente la conclusione è che non è possibile assegnare con garbo i prototipi a oggetti (letterali) esistenti. Invece, i nuovi oggetti devono essere creati usando una funzione di costruzione. –

+0

@NielsB. Bene, mentre può essere possibile, non lo vuoi fare, dal momento che vuoi solo "introdurre" disponibile per oggetti _certain_, nel mio esempio un'istanza di 'Person'. – rgthree

+0

Sì, lo so. Non voglio sostituire il prototipo per TUTTI gli oggetti, ma intuitivamente mi sembra più efficiente iterare su un array e sostituire il riferimento del prototipo invece di creare un nuovo set di oggetti. –

3

fare una semplice Person classe:

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

Dire, si avere questa matrice:

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

Converti people-Person array:

012.

aggiungere il metodo di prototipo:

Person.prototype.introduce = introduce 
2

Creare una classe persona e utilizzare 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

Vorrei suggerire la creazione di una struttura per queste persone.

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

E poi iterare per costruire le persone.

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

Ora che le persone sono costruite, forse vorresti consentire loro di presentarsi. Puoi semplicemente estendere la tua "classe" Persona (definizione).

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

che permetterà loro di utilizzare questa funzione

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

Se non si vuole ri costruire ogni volta che si potrebbe provare questo:

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(); 

Se gli oggetti JSON hanno molti membri quindi questo potrebbe salvarti dal doverli copiare nella funzione di costruzione, ma non sono sicuro che tu stia ottenendo più prestazioni da esso.

Problemi correlati