2009-07-05 20 views
5

JSON डेटा को deserialize करने और प्रत्येक ऑब्जेक्ट के प्रोटोटाइप को अद्यतन करने और एक सामान्य कार्य का वारिस करने का प्रयास।जावास्क्रिप्ट प्रोटोटाइप eval deserialization के बाद अपरिभाषित

हालांकि, निम्न स्क्रिप्ट त्रुटि "लोगों [0] .getFullName एक फ़ंक्शन नहीं है"। Deserialized वस्तुओं के लिए प्रोटोटाइप असाइनमेंट के बाद अपरिभाषित प्रतीत होता है।

<html> 
<head> 
<script> 
var json = '[ {"firstName": "John", "lastName": "Smith"}, {"firstName": "Nancy", "lastName": "Jones"} ]'; 
var people; 
eval('people = ' + json); 

function Person() { } 

Person.prototype.getFullName = function() { 
    return this.firstName + ' ' + this.lastName; 
} 

//assign prototype 
for(var i=0; i < people.length; i++){ 
    people[i].prototype = new Person(); 
} 


if(people[0].getFullName() !== 'John Smith') 
    alert('Expected fullname to be John Smith but was ' + people[0].getFullName()); 
</script> 
</head> 
</html> 

उत्तर

2

prototype संपत्ति कंस्ट्रक्टर्स, उदाहरणों की नहीं की संपत्ति है। क्या आप देख रहे हैं संपत्ति __proto__ है:

people[i].__proto__ = new Person(); 

बुरी खबर है कि यह सभी ब्राउज़रों में काम नहीं करता है। यह फ़ायरफ़ॉक्स और सफारी में काम करता है, यह आईई में काम नहीं करता है। लोगों की अपनी सरणी को तुरंत चालू करने के लिए रचनाकारों का उपयोग करना एक विकल्प है। दुर्भाग्य से आप सभी गुण कॉपी करना होगा:

function Person(obj) { 
    for (var property in obj) { 
     this[property] = obj[property]; 
    } 
    return this; 
} 
Person.prototype.getFullName = function() { 
    return this.firstName + ' ' + this.lastName; 
} 

var people; 
eval('people = ' + json); 
for(var i=0; i < people.length; i++) { 
    people[i] = new Person(people[i]); 
} 
+0

सीटीओआर पर प्रॉपर्टी कॉपी लूप जो मैं करने की कोशिश कर रहा हूं उसके लिए सबसे अच्छा देर से समाधान प्रदान करता है। धन्यवाद! –

4

एक वस्तु एक्स कि एक्स = नया व्यक्ति() से जुड़ा हुआ है द्वारा बनाई गई है/Person.prototype से विरासत है, लेकिन जहाँ तक ECMA मानक का सवाल है आप के लिए x.prototype बदल नहीं सकते उस लिंक/विरासत को बाद में बदलें, यह "जादू शक्ति" केवल नया कीवर्ड है।
गैर-मानक संपत्ति __proto__ के माध्यम से किसी ऑब्जेक्ट को बनाए जाने के बाद मोज़िला ऑब्जेक्ट लिंक को बदलने का एक तरीका प्रदान करता है।

मोज़िला केवल:

//assign prototype 
for(var i=0; i < people.length; i++){ 
    people[i].__proto__ = Person.prototype; 
} 

कहीं भी काम करना चाहिए:

function Person(data) { this.data = data; } 
Person.prototype.getFullName = function() { 
    return this.data.firstName + ' ' + this.data.lastName; 
} 

eval('people = ' + json); 
//assign prototype 
for(var i=0; i < people.length; i++){ 
    people[i] = new Person(people[i]); 
} 
+0

आह ... धन्यवाद। डेटा तर्क के साथ निर्माण का क्रॉस-ब्राउज़र उदाहरण काम करता है। मैं इसके साथ कुछ और प्रयोग करूँगा। धन्यवाद! –

2

मूल रूप से, आप एक व्यक्ति वस्तु में JSON ऑब्जेक्ट प्राप्त करने के लिए, और फिर getFullName सिर्फ लागू होता है। मैंने फिर से लिखा है कि आपके पास काम करने के लिए थोड़ा सा था। शायद और भी बेहतर तरीके से है, लेकिन मुझे लगता है कि यह तुम क्या करने का इरादा कर रहे थे क्या है ... आत्मज्ञान के लिए

<html> 
<head> 
<script> 
//NOTE: Sending around JSON arrays leaves bad security holes for non-IE browsers (__defineSetter__) 
var json = '[ {"firstName": "John", "lastName": "Smith"}, {"firstName": "Nancy", "lastName": "Jones"} ]'; 
//Persons is just a temporary JSON array 
var persons = eval(json); 

//constructor takes optional object instance and copies all properties if it gets one 
function Person(person) { 
    if (person) { 
     for(var prop in person) 
     this[prop] = person[prop]; 
    } 
} 

//Prototype applies to all Person objects 
Person.prototype.getFullName = function() { 
    return this.firstName + ' ' + this.lastName; 
} 

//Create People array 
var people = new Array(); 
for(var i=0; i < persons.length; i++){ 
    people[i] = new Person(persons[i]); 
} 

//Now do your check 
if(people[0].getFullName() !== 'John Smith') 
    alert('Expected fullname to be John Smith but was ' + people[0].getFullName()); 

</script> 
</head> 
</html> 
+0

धन्यवाद टोनी। मैं उत्पादन में eval के बजाय ASP.NET Sys.Serialization नामस्थान का उपयोग कर रहा हूँ। जेएसओएन डेटा भेजने में शामिल संभावित सुरक्षा जोखिमों के बारे में अधिक जानने के लिए उत्सुक होंगे। –

+0

एक नज़र डालें: http://haacked.com/archive/2009/06/25/json-hijacking.aspx –

2
for(var i=0; i < people.length; i++){ 
     people[i].getFullName = Person.prototype.getFullName; } 
+0

यह अक्षम है क्योंकि यह प्रत्येक उदाहरण पर विधि की एक प्रति बनाता है। – kpozin

संबंधित मुद्दे