Сериализация дочернего объекта в родительском объекте в JavaScript - PullRequest
1 голос
/ 12 марта 2012

Этот вопрос является продолжением моего последнего вопроса: Сериализация и методы JavaScript .Хотя это связано, я считаю, что это отличается, поэтому я начал эту тему.Независимо от того ...

У меня есть сложное дерево объектов, которое мне нужно передавать между страницами.Из-за этого я пытаюсь сериализовать и десериализовать мои объекты.В частности, один из моих объектов имеет несколько коллекций дочерних объектов.У каждого из этих дочерних типов объектов есть функция, которую я пытаюсь вызвать.К сожалению, мне не повезло.Я настроил тестовый проект, пытаясь изолировать проблему и разобраться в ней.В настоящее время мои объекты JavaScript определены в отдельном файле objects.js.Этот файл выглядит следующим образом:

objects.js

function MyChild() { this.init(); }
MyChild.prototype = {
    data: {
        id: 0,
        fullName: "",
    },

    init: function () {

    },

    save: function (key) {

    },

    load: function (key) {

    },

    test: function () {
        alert("Testing Child functions");
    }
}

function MyParent() { this.init(); }
MyParent.prototype = {
    data: {
        id: "",
        children: null
    },

    init: function () {
        this.data.children = [];
    },

    save: function (key) {
        window.localStorage.setItem(key, JSON.stringify(this.data));
    },

    load: function (key) {
        var temp = window.localStorage.getItem(key);
        if (temp != null) {
            this.data = JSON.parse(temp);
            $.each(this.data.children, function (i, r) {
            });
        }
    },

    test: function () {
        alert("Testing Parent functions");
    }
}

Я создаю, сериализую, десериализую и пытаюсь взаимодействовать с этими объектами в файле .html.,Этот файл .html показан здесь:

test.html

<div>
    <input id="button1" type="button" value="Create Object Tree" onclick="button1Click();" /><br />
    <input id="button2" type="button" value="Retrieve and Execute" onclick="button2Click();" /><br />
</div>

<script type="text/javascript">
    function button1Click() {
        var child = new MyChild();
        child.data.id = 1;

        var p = new MyParent();
        p.data.id = "A";
        p.data.children.push(child);
        p.save("A");
    }

    function button2Click() {
        var storedParent = new MyParent();
        storedParent.load("A");

        storedParent.test();                          // This works
        alert(storedParent.data.children.length);     // This displays "1" like I would expect
        alert(storedParent.data.children[0].data.id); // This does NOT work. 
        storedParent.data.children[0].test();         // This does NOT work.   
    }
</script>

Я не уверен, что делаю неправильно.Может кто-нибудь, пожалуйста, помогите мне понять это?Сомоне, пожалуйста, помогите мне исправить мой пример.У меня есть догадка, что я не сериализую объекты MyChild должным образом.Но я не понимаю, как я должен сериализовать / десериализовать их в отношении MyParent.

Спасибо!

1 Ответ

2 голосов
/ 12 марта 2012

Вам необходимо хранить data внутри каждого объекта, а не внутри его prototype.

Данные, хранящиеся в prototype объекта, совместно используются всеми экземплярами и не будут сериализованы JSON.stringify, поэтому данные вашего объекта никогда не попадут в локальное хранилище.

Чтобы исправить, добавьте данные к this в функции this.init():

MyChild.prototype = {
    init: function() {
        this.data = {
            id: 0,
            fullName: ""
        };
    },
    ...
}

MyParent.prototype = {
    init: function() {
        this.data = {
            id: "",
            children: []
        }
    },
    ...
}

Рабочий образец при http://jsfiddle.net/alnitak/fdwVB/

Обратите внимание, что прикрепить функции из MyChild к полученным данным довольно сложно. Код ниже, кажется, работает:

load: function(key) {
    var temp = window.localStorage.getItem(key);
    if (temp != null) {
        this.data = JSON.parse(temp);
        var children = this.data.children;
        for (var i = 0; i < children.length; ++i) {
            children[i] = $.extend(new MyChild(), children[i]);
        }
    }
},

Но обратите внимание, что он работает путем создания нового дочернего элемента «по умолчанию» для каждой извлеченной записи, а затем перезаписывает данные этого дочернего элемента сериализованными значениями.

Это может быть проблематично, если конструктор имеет «побочные эффекты».

Лучшим подходом может быть позволить конструктору MyChild() взять необязательный полный объект начальных значений для использования вместо значений по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...