tag - Javascript: encordar objeto(incluyendo miembros de tipo de función)
title title html (5)
Estoy buscando una solución para serializar (y deserializar) objetos de Javascript en una cadena en todos los navegadores, incluidos los miembros del objeto que resultan ser funciones. Un objeto típico se verá así:
{
color: ''red'',
doSomething: function (arg) {
alert(''Do someting called with '' + arg);
}
}
doSomething () solo contendrá variables locales (¡no es necesario que también serialice el contexto de llamada!).
JSON.stringify () ignorará el miembro ''doSomething'' porque es una función. Sabía que el método toSource () hará lo que quiero pero es específico de FF.
Algo como esto...
(function(o) {
var s = "";
for (var x in o) {
s += x + ": " + o[x] + "/n";
}
return s;
})(obj)
Nota: esta es una expresión. Devuelve una representación de cadena del objeto que se pasa como un argumento (en mi ejemplo, estoy pasando una variable llamada obj).
También puede anular el método toString del prototipo del Objeto:
Object.prototype.toString = function() {
// define what string you want to return when toString is called on objects
}
El complemento JSONfn es exactamente lo que estás buscando.
http://www.eslinstructor.net/jsonfn/
--Vadim
Es imposible sin la ayuda del propio objeto. Por ejemplo, ¿cómo serializaría el resultado de esta expresión?
(function () { var x; return { get: function () { return x; }, set: function (y) { return x = y; } }; })();
Si solo toma el texto de la función, entonces cuando deserialice, x
se referirá a la variable global, no a una en un cierre. Además, si su función se cierra sobre el estado del navegador (como una referencia a un div), tendría que pensar qué quiere decir eso.
Por supuesto, puede escribir sus propios métodos específicos para objetos individuales que codifiquen qué semántica quiere que tengan las referencias a otros objetos.
Puedes usar JSON.stringify
con un replacer
como:
JSON.stringify({
color: ''red'',
doSomething: function (arg) {
alert(''Do someting called with '' + arg);
}
}, function(key, val) {
return (typeof val === ''function'') ? '''' + val : val;
});
Una manera rápida y sucia sería así:
Object.prototype.toJSON = function() {
var sobj = {}, i;
for (i in this)
if (this.hasOwnProperty(i))
sobj[i] = typeof this[i] == ''function'' ?
this[i].toString() : this[i];
return sobj;
};
Obviamente, esto afectará la serialización de cada objeto en su código, y podría hacer tropezar el código niave usando filtros sin filtrar for in
. La forma "adecuada" sería escribir una función recursiva que agregaría la función toJSON
en todos los miembros descendientes de cualquier objeto dado, tratando con referencias circulares y demás. Sin embargo, suponiendo que solo haya un solo hilo (no trabajadores web), este método debería funcionar y no producir efectos secundarios no deseados.
Se debe agregar una función similar al prototipo de Array para anular los Objetos devolviendo una matriz y no un objeto. Otra opción sería adjuntar una sola y permitirle devolver selectivamente una matriz o un objeto dependiendo de la propia naturaleza de los objetos, pero probablemente sería más lento.
function JSONstringifyWithFuncs(obj) {
Object.prototype.toJSON = function() {
var sobj = {}, i;
for (i in this)
if (this.hasOwnProperty(i))
sobj[i] = typeof this[i] == ''function'' ?
this[i].toString() : this[i];
return sobj;
};
Array.prototype.toJSON = function() {
var sarr = [], i;
for (i = 0 ; i < this.length; i++)
sarr.push(typeof this[i] == ''function'' ? this[i].toString() : this[i]);
return sarr;
};
var str = JSON.stringify(obj);
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
return str;
}