Javascript:如何将对象的JSON数组重新转换为Object类型共享原型?

时间:2022-09-29 16:25:26

If you have an array of product objects created from JSON, how would you add a prototype method to the product objects so that they all point to the same method? How would you train JavaScript to recognize all product objects in an array are instances of the same class without recreating them?

如果您有一个从JSON创建的产品对象数组,那么如何将原型方法添加到产品对象中,以便它们都指向相同的方法?如何训练JavaScript识别数组中的所有产品对象是否是同一个类的实例而不重新创建它们?

If I pull down a JSON array of Products for example, and want each product in the array to have a prototype method, how would I add the single prototype method to each copy of Product?

例如,如果我下拉产品的JSON数组,并希望数组中的每个产品都有原型方法,我如何将单个原型方法添加到每个产品副本?

I first thought to have a Product constructor that takes product JSON data as a parameter and returns a new Product with prototypes, etc. which would replace the data send from the server. I would think this would be impractical because you are recreating the objects. We just want to add functions common to all objects.

我首先想到的是一个Product构造函数,它将产品JSON数据作为参数,并返回一个带有原型等的新产品,它将取代从服务器发送的数据。我认为这是不切实际的,因为你正在重新创建对象。我们只想添加所有对象共有的函数。

Is it possible to $.extend an object's prototype properties to the JSON object so that each JSON object would refer to exactly the same functions (not a copy of)?

是否可以$。将对象的原型属性扩展到JSON对象,以便每个JSON对象引用完全相同的函数(而不是副本)?

For example:

例如:

var Products = [];
Products[0] = {};
Products[0].ID = 7;
Products[0].prototype.GetID = function() { return this.ID; };
Products[1].ID = 8;
Products[1].prototype = Products[0].prototype;  // ??

I know that looks bad, but what if you JQuery $.extend the methods to each Product object prototype: create an object loaded with prototypes then $.extend that object over the existing Product objects? How would you code that? What are the better possibilities?

我知道这看起来很糟糕,但如果你JQuery $。扩展每个Product对象原型的方法怎么办:创建一个加载了原型的对象然后$ .extend那个对象超过现有的Product对象?你会怎么编码?有什么更好的可能性?

6 个解决方案

#1


1  

So, if I'm getting this all correctly, this is a more complete example of KOGI's idea:

所以,如果我正确地得到这一点,这是KOGI想法的一个更完整的例子:

// Create a person class
function Person( firstName, lastName ) {
    var aPerson = {
        firstName:  firstName,
        lastName:   lastName
    }

    // Adds methods to an object to make it of type "person"
    aPerson = addPersonMethods( aPerson );
    return aPerson;
}
function addPersonMethods( obj ) {
    obj.nameFirstLast = personNameFirstLast;
    obj.nameLastFirst = personNameLastFirst;
    return obj;
}
function personNameFirstLast() {
    return this.firstName + ' ' + this.lastName;
}
function personNameLastFirst() {
    return this.lastName + ', ' + this.firstName;
}

So, with this structure, you are defining the methods to be added in the addPersonMethods function. This way, the methods of an object are defined in a single place and you can then do something like this:

因此,使用此结构,您将定义要在addPersonMethods函数中添加的方法。这样,对象的方法在一个地方定义,然后你可以这样做:

// Given a variable "json" with the person json data
var personWithNoMethods = JSON.parse( json );    // Use whatever parser you want
var person = addPersonMethods( personWithNoMethods );

#2


2  

For one, you're not modifying the Products[0].prototype, you're modifying Object.prototype, which will put that function on the prototype of all objects, as well as making it enumerable in every for loop that touches an Object.

首先,你没有修改Products [0] .prototype,你正在修改Object.prototype,它会将该函数放在所有对象的原型上,并使其在每个触及Object的for循环中都可枚举。 。

Also, that isn't the proper way to modify a prototype, and ({}).prototype.something will throw a TypeError as .prototype isn't defined. You want to set it with ({}).__proto__.something.

此外,这不是修改原型的正确方法,并且({})。prototype.something将抛出TypeError,因为未定义.prototype。你想用({}).__ proto __设置它。

If you want it to be a certain instance you need to create that instance, otherwise it will be an instance of Object.

如果您希望它是某个实例,则需要创建该实例,否则它将是Object的实例。

You probably want something like:

你可能想要这样的东西:

var Product = function(ID) {
    if (!this instanceof Product)
        return new Product(ID);

    this.ID = ID;

    return this;
};

Product.prototype.GetID = function() { 
    return this.ID;
};

Then, fill the array by calling new Product(7) or whatever the ID is.

然后,通过调用新的Product(7)或任何ID来填充数组。

#3


2  

First, one problem is that prototype methods are associated when the object is created, so assigning to an object's prototype will not work:

首先,一个问题是在创建对象时关联原型方法,因此分配给对象的原型将不起作用:

var Products = [];
Products[0] = {};
Products[0].prototype.foo = function () { return 'hello' } // ***

Products[0].foo(); // call to undefined function

(*** Actually, the code fails here, because prototype is undefined.)

(***实际上,代码在这里失败了,因为原型未定义。)

So in order to attach objects, you'll need to assign actual functions to the object:

因此,为了附加对象,您需要将实际函数分配给对象:

Products[0].foo = function () { return 'hello'; };

You can create a helper function to do so:

您可以创建一个辅助函数来执行此操作:

var attachFoo = (function () { // Create a new variable scope, so foo and
                               // bar is not part of the global namespace

    function foo() { return this.name; }
    function bar() { return 'hello'; }

    return function (obj) {
        obj.foo = foo;
        obj.bar = bar;
        return obj; // This line is actually optional,
                    // as the function /modifies/ the current
                    // object rather than creating a new one
    };

}());

attachFoo(Products[0]);
attachFoo(Products[1]);

// - OR -
Products.forEach(attachFoo);

By doing it this way, your obj.foos and obj.bars will all be referencing the same foo() and bar().

通过这种方式,你的obj.foos和obj.bars都将引用相同的foo()和bar()。

#4


1  

You could do this...

你可以这样做......

function product( )
{
   this.getId = product_getId;

    // -- create a new product object
}

function product_getId( )
{
   return this.id;
}

This way, although you will have several instances of the product class, they all point to the instance of the function.

这样,虽然您将拥有产品类的多个实例,但它们都指向该函数的实例。

#5


1  

Could try doing something like this (without jquery) Basic prototypal object:

可以尝试做这样的事情(没有jquery)基本原型对象:

function Product(id){
    this.id = id;
}
Product.prototype.getId() = function(){return this.id;};

var Products = [];
Products[0] = new Product(7);
Products[1] = new Product(8);
Products[2] = new Product(9);

alert(Products[2].getId());

#6


1  

IMO I found a pretty good answer right here:

IMO我在这里找到了一个很好的答案:

Return String from Cross-domain AJAX Request

从跨域AJAX请求返回字符串

...I could serialize my data in the service as a JSON string and then further wrap that in JSONP format? I guess when it comes over to the client it would give the JSON string to the callback function. That's not a bad idea. I guess I would also have the option of sending a non-JSON string which might allow me to just use eval in the callback function to create new Person objects. I'm thinking this would be a more efficient solution in both speed and memory usage client-side.

...我可以将服务中的数据序列化为JSON字符串,然后以JSONP格式进一步包装它?我想当它到达客户端时,它会将JSON字符串提供给回调函数。这不是一个坏主意。我想我也可以选择发送一个非JSON字符串,这可能允许我在回调函数中使用eval来创建新的Person对象。我认为这将是客户端速度和内存使用方面更有效的解决方案。

#1


1  

So, if I'm getting this all correctly, this is a more complete example of KOGI's idea:

所以,如果我正确地得到这一点,这是KOGI想法的一个更完整的例子:

// Create a person class
function Person( firstName, lastName ) {
    var aPerson = {
        firstName:  firstName,
        lastName:   lastName
    }

    // Adds methods to an object to make it of type "person"
    aPerson = addPersonMethods( aPerson );
    return aPerson;
}
function addPersonMethods( obj ) {
    obj.nameFirstLast = personNameFirstLast;
    obj.nameLastFirst = personNameLastFirst;
    return obj;
}
function personNameFirstLast() {
    return this.firstName + ' ' + this.lastName;
}
function personNameLastFirst() {
    return this.lastName + ', ' + this.firstName;
}

So, with this structure, you are defining the methods to be added in the addPersonMethods function. This way, the methods of an object are defined in a single place and you can then do something like this:

因此,使用此结构,您将定义要在addPersonMethods函数中添加的方法。这样,对象的方法在一个地方定义,然后你可以这样做:

// Given a variable "json" with the person json data
var personWithNoMethods = JSON.parse( json );    // Use whatever parser you want
var person = addPersonMethods( personWithNoMethods );

#2


2  

For one, you're not modifying the Products[0].prototype, you're modifying Object.prototype, which will put that function on the prototype of all objects, as well as making it enumerable in every for loop that touches an Object.

首先,你没有修改Products [0] .prototype,你正在修改Object.prototype,它会将该函数放在所有对象的原型上,并使其在每个触及Object的for循环中都可枚举。 。

Also, that isn't the proper way to modify a prototype, and ({}).prototype.something will throw a TypeError as .prototype isn't defined. You want to set it with ({}).__proto__.something.

此外,这不是修改原型的正确方法,并且({})。prototype.something将抛出TypeError,因为未定义.prototype。你想用({}).__ proto __设置它。

If you want it to be a certain instance you need to create that instance, otherwise it will be an instance of Object.

如果您希望它是某个实例,则需要创建该实例,否则它将是Object的实例。

You probably want something like:

你可能想要这样的东西:

var Product = function(ID) {
    if (!this instanceof Product)
        return new Product(ID);

    this.ID = ID;

    return this;
};

Product.prototype.GetID = function() { 
    return this.ID;
};

Then, fill the array by calling new Product(7) or whatever the ID is.

然后,通过调用新的Product(7)或任何ID来填充数组。

#3


2  

First, one problem is that prototype methods are associated when the object is created, so assigning to an object's prototype will not work:

首先,一个问题是在创建对象时关联原型方法,因此分配给对象的原型将不起作用:

var Products = [];
Products[0] = {};
Products[0].prototype.foo = function () { return 'hello' } // ***

Products[0].foo(); // call to undefined function

(*** Actually, the code fails here, because prototype is undefined.)

(***实际上,代码在这里失败了,因为原型未定义。)

So in order to attach objects, you'll need to assign actual functions to the object:

因此,为了附加对象,您需要将实际函数分配给对象:

Products[0].foo = function () { return 'hello'; };

You can create a helper function to do so:

您可以创建一个辅助函数来执行此操作:

var attachFoo = (function () { // Create a new variable scope, so foo and
                               // bar is not part of the global namespace

    function foo() { return this.name; }
    function bar() { return 'hello'; }

    return function (obj) {
        obj.foo = foo;
        obj.bar = bar;
        return obj; // This line is actually optional,
                    // as the function /modifies/ the current
                    // object rather than creating a new one
    };

}());

attachFoo(Products[0]);
attachFoo(Products[1]);

// - OR -
Products.forEach(attachFoo);

By doing it this way, your obj.foos and obj.bars will all be referencing the same foo() and bar().

通过这种方式,你的obj.foos和obj.bars都将引用相同的foo()和bar()。

#4


1  

You could do this...

你可以这样做......

function product( )
{
   this.getId = product_getId;

    // -- create a new product object
}

function product_getId( )
{
   return this.id;
}

This way, although you will have several instances of the product class, they all point to the instance of the function.

这样,虽然您将拥有产品类的多个实例,但它们都指向该函数的实例。

#5


1  

Could try doing something like this (without jquery) Basic prototypal object:

可以尝试做这样的事情(没有jquery)基本原型对象:

function Product(id){
    this.id = id;
}
Product.prototype.getId() = function(){return this.id;};

var Products = [];
Products[0] = new Product(7);
Products[1] = new Product(8);
Products[2] = new Product(9);

alert(Products[2].getId());

#6


1  

IMO I found a pretty good answer right here:

IMO我在这里找到了一个很好的答案:

Return String from Cross-domain AJAX Request

从跨域AJAX请求返回字符串

...I could serialize my data in the service as a JSON string and then further wrap that in JSONP format? I guess when it comes over to the client it would give the JSON string to the callback function. That's not a bad idea. I guess I would also have the option of sending a non-JSON string which might allow me to just use eval in the callback function to create new Person objects. I'm thinking this would be a more efficient solution in both speed and memory usage client-side.

...我可以将服务中的数据序列化为JSON字符串,然后以JSONP格式进一步包装它?我想当它到达客户端时,它会将JSON字符串提供给回调函数。这不是一个坏主意。我想我也可以选择发送一个非JSON字符串,这可能允许我在回调函数中使用eval来创建新的Person对象。我认为这将是客户端速度和内存使用方面更有效的解决方案。