eval 反序列化后 JavaScript 原型未定义

发布于 2024-07-26 08:35:35 字数 721 浏览 2 评论 0原文

尝试反序列化 JSON 数据并更新每个对象的原型并继承公共函数。

但是,以下脚本会引发错误“people[0].getFullName 不是函数”。 反序列化对象的原型在赋值后似乎未定义。

<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>

Attempting to deserialize JSON data and update each object's prototype and inherit a common function.

However, the following script throws error "people[0].getFullName is not a function". The prototype for deserialized objects appears to be undefined after assignment.

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对不⑦ 2024-08-02 08:35:35

由 x=new Person() 创建的对象 x 链接到/继承自 Person.prototype,但就 ecma 标准而言,您不能更改 x.prototype 来更改它之后的链接/继承,这就是只有new关键字才拥有的“魔力”。
Mozilla 似乎提供了一种在通过非标准属性创建对象后更改对象链接的方法 __proto__

仅限 Mozilla:

//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]);
}

An object x that is created by x=new Person() is linked to/inherits from Person.prototype, but as far as the ecma standard is concerned you cannot change x.prototype in order to change that link/inheritance afterwards, that's the "magic power" only the new keyword possesses.
Mozilla seems to offer a way to change the object link after an object has been created through the non-standard property __proto__.

Mozilla-only:

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

should work anywhere:

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]);
}
空宴 2024-08-02 08:35:35

prototype 属性是构造函数的属性,而不是实例的属性。 您正在寻找的是属性 __proto__

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

坏消息是它不适用于所有浏览器。 它在 Firefox 和 Safari 中工作,但在 IE 中不起作用。 另一种方法是使用构造函数来实例化您的人员数组。 不幸的是,您必须复制所有属性:

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]);
}

The prototype property is a property of constructors, not of instances. What you are looking for is the property __proto__:

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

The bad news is that it does not work in all browsers. It does work in Firefox and Safari, it does not work in IE. An alternative is to use constructors to instantiate your array of people. Unfortunately you'll have to copy all properties:

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]);
}
空城旧梦 2024-08-02 08:35:35

基本上,您必须将 JSON 对象转换为 Person 对象,然后 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>

Basically, you have to get the JSON object INTO a Person object, and then the getFullName just applies. I've rewritten what you had slightly to work. There's probably even better ways, but I think this is what you were intending to do...

<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>
—━☆沉默づ 2024-08-02 08:35:35
for(var i=0; i < people.length; i++){
      people[i].getFullName = Person.prototype.getFullName; }
for(var i=0; i < people.length; i++){
      people[i].getFullName = Person.prototype.getFullName; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文