感谢您的回复。虽然plalx的答案完美适用于特定对象,但我想要有更通用的东西,它适用于任何对象。
另一种解决方案可以使用是这样的:
function construct(constructor, args, vars) {
function Obj() {
var variables = vars
return constructor.apply(this, args);
}
Obj.prototype = constructor.prototype;
return new Obj();
}
function addFunction(anObject, aFunction, variables) {
var objectSource = anObject.toString();
var functionSource = aFunction.toString();
objectSource = objectSource.substring(0,objectSource.length-1);
var functionName = functionSource.substring(9, functionSource.indexOf('('));
var functionArgs = functionSource.substring(functionSource.indexOf('('), functionSource.indexOf('{')+1);
var functionBody = functionSource.substring(functionSource.indexOf('{')+1, functionSource.length);
return objectSource + "this." + functionName + " = function" +
functionArgs + "var variables = " + variables + ";\n" + functionBody + "}";
}
function makeSerializable(anObject) {
var obj = JSON.stringify(anObject, function(key, val) {
return ((typeof val === "function") ? val+'' : val);
});
var variables = [];
while(obj.indexOf("var") > -1) {
var subString = obj.substring(obj.indexOf("var")+3, obj.length-1);
while (subString[0] == " ")
subString = subString.replace(" ", "");
var varEnd = Math.min(subString.indexOf(" "), subString.indexOf(";"));
var varName = subString.substring(0, varEnd);
variables.push(varName);
obj = obj.replace("var","");
}
var anObjectSource = addFunction(anObject,
function serialize(){
var vars = [];
console.log("hidden variables:" + variables);
variables.forEach(function(variable) {
console.log(variable + ": " + eval(variable));
vars += JSON.stringify([variable, eval(variable)]);
});
var serialized = [];
serialized.push(vars);
for (var func in this){
if (func != "serialize")
serialized.push([func, this[func].toString()]);
}
return JSON.stringify(serialized);
},
JSON.stringify(variables));
anObject = Function("return " + anObjectSource)();
var params = Array.prototype.slice.call(arguments);
params.shift();
return construct(anObject, params, variables);
}
这可以让你任何对象序列化的所有要素,包括隐藏变量。然后,serialize()函数可以替换为隐藏变量的自定义字符串表示形式,可以在将字符串表示形式反序列化为对象时使用它。
用法:
function anObject(){
var x = 1;
var y = [1,2];
var z = {"name": "test"};
this.test = function(){return x;};
this.add = function(a){x+a;};
}
var test = makeSerializable(anObject)
test.serialize()
>>>["[\"x\",1][\"y\",[1,2]][\"z\",{\"name\":\"test\"}]",["test","function(){return x;}"],["add","function (a){x+a;}"]]
您不能访问封闭的执行上下文/环境,所以我真的不认为这是可能是你正在尝试做的。 –
您可以使用JSON.parse()上的复位参数将字符串化的方法转换为使用eval或Function的实际函数。您还需要定义Function.prototype.toJSON来生成您的reviver函数可以检测到的吸烟枪签名。有了这两个部分,并且没有方法需要外部变量关闭并且发布使用的属性,则可以实现您的目标。 – dandavis