У меня есть приложение, которое позволяет пользователям создавать объекты и сохранять их (в Таблица MySQL в виде строк) для дальнейшего использования. Объект может быть:
function Obj() {
this.label = "new object";
}
Obj.prototype.setLabel = function(newLabel) {
this.label = newLabel;
}
Если я использую JSON.stringify для этого объекта, я получу информацию только о Obj.label
(строковый объект будет такой строкой, как {label: "новый объект"}
. Если я сохраню эту строку и хочу разрешить моему пользователю получить объект позже, Метод setLabel
будет утерян.
Итак, мой вопрос: как я могу повторно создать экземпляр объекта, чтобы он сохранял свойства, сохраненные благодаря JSON.stringify, но также возвращал различные методы, которые должны принадлежать его прототип. Как бы вы это сделали? Я думал о чем-то вроде "создать пустой объект" и "объединить его с сохраненными свойствами", но я не могу заставить его работать.
Вы действительно можете создать пустой экземпляр, а затем объединить его с данными. Я рекомендую использовать библиотечную функцию для простоты использования (например, jQuery.extend
).
У вас были некоторые ошибки (function ... = function(...)
, а JSON требует, чтобы ключи были окружены "
).
var data = '{"label": "new object"}'; // JSON
var inst = new Obj; // empty instance
jQuery.extend(inst, JSON.parse(data)); // merge
Обратите внимание, что при таком слиянии свойства устанавливаются напрямую, поэтому, если setLabel
выполняет некоторые проверки, это не будет сделано таким образом.
Если вы хотите использовать сеттеры Obj:
Obj.createFromJSON = function(json){
if(typeof json === "string") // if json is a string
json = JSON.parse(json); // we convert it to an object
var obj = new Obj(), setter; // we declare the object we will return
for(var key in json){ // for all properties
setter = "set"+key[0].toUpperCase()+key.substr(1); // we get the name of the setter for that property (e.g. : key=property => setter=setProperty
// following the OP's comment, we check if the setter exists :
if(setter in obj){
obj[setter](json[key]); // we call the setter
}
else{ // if not, we set it directly
obj[key] = json[key];
}
}
return obj; // we finally return the instance
};
Для этого у вашего класса должны быть сеттеры для всех его свойств. Этот метод является статическим, поэтому вы можете использовать его так:
var instance = Obj.createFromJSON({"label":"MyLabel"});
var instance2 = Obj.createFromJSON('{"label":"MyLabel"}');
JavaScript - это основанный на прототипах язык программирования , который является бесклассовым языком, в котором ориентация на объекты достигается путем клонирования существующих объектов, которые служат прототипами.
Сериализация JSON будет учитывать любые методы, например, если у вас есть объект
var x = {
a: 4
getText: function() {
return x.a;
}
};
Вы получите только { a:4 }
, где метод getText
пропускается сериализатором.
Я столкнулся с этой же проблемой год назад, и мне пришлось поддерживать отдельный вспомогательный класс для каждого объекта моего домена и использовать $.extend()
его для моего десериализованного объекта , когда нужно, просто как иметь методы для базового класса для доменных объектов .