2009-07-05 6 views
5

JSON 데이터를 deserialize하고 각 객체의 프로토 타입을 업데이트하고 공통 함수를 상속합니다.eval deserialization 후 자바 스크립트 프로토 타입이 정의되지 않았습니다.

그러나 다음 스크립트는 "people [0] .getFullName은 함수가 아닙니다."라는 오류를 발생시킵니다. deserialize 된 객체의 프로토 타입은 할당 후에 정의되지 않은 것처럼 보입니다.

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

나쁜 소식은이 모든 브라우저에서 작동하지 않습니다 것입니다. Firefox 및 Safari에서 작동하지만 Internet Explorer에서는 작동하지 않습니다. 대안은 생성자를 사용하여 사용자 배열을 인스턴스화하는 것입니다.

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

CTOR의 속성 복사 루프는 내가하려고하는 것에 대해 가장 늦은 바운드 해결책을 제공합니다. 고마워! –

4

가 연결되어() X = 새로운 사람에 의해 만들어진 객체의 X는/Person.prototype에서 상속하지만, 멀리 ECMA 표준에 관한 한 당신을 위해 x.prototype을 변경할 수 없습니다 나중에 그 링크/상속을 변경, 그 "마법의 힘"은 새로운 키워드 만 소유하고 있습니다.
Mozilla는 비표준 속성 __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

아 ... 감사합니다 ...이 아마 더 나은 방법이지만, 나는 이것이 당신이하려는 있었는지 생각합니다. 데이터 arg로 구성하는 브라우저 간 예제가 작동합니다. 나는 이것을 좀 더 실험 할 것이다. 고마워! –

2

는 기본적으로, 당신은 Person 객체로 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

감사합니다. Tony. 프로덕션 환경에서 평가 대신 ASP.NET Sys.Serialization 네임 스페이스를 사용하고 있습니다. JSON 데이터를 전송하는 것과 관련된 잠재적 인 보안 위험에 대해 더 자세히 알고 싶을 것입니다. –

+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