我們使用可選的第二replacer參數JSON.stringify
來預處理鍵/值,在字符串化形式發射功能:
function stringify_with_fns(obj) {
return JSON.stringify(obj, function(key, value) {
return typeof value === "function" ? value.toString() : value;
});
}
然後打開字符串化功能回到實際功能的出路,我們使用可選的第二個reviver參數JSON.parse
,如
function parse_with_fns(json) {
return JSON.parse(json, function(key, value) {
if (looks_like_a_function_string(value)) {
return make_function_from_string(value);
} else {
return value;
}
});
}
looks_like_a_function_string
僅僅是一個正則表達式,並在make_function_from_string
可先切開,使用eval
:
function looks_like_a_function_string(value) {
return /^function.*?\(.*?\)\s*\{.*\}$/.test(value);
}
function make_function_from_string(value) {
return eval(value);
}
爲了避免eval
,我們可以挑選除了功能串找到它的參數和身體,所以我們可以將它們傳遞給new Function
:
function make_function_from_string(value) {
var args = value
.replace(/\/\/.*$|\/\*[\s\S]*?\*\//mg, '') //strip comments
.match(/\(.*?\)/m)[0] //find argument list
.replace(/^\(|\)$/, '') //remove parens
.match(/[^\s(),]+/g) || [], //find arguments
body = value.match(/\{(.*)\}/)[1] //extract body between curlies
return Function.apply(0, args.concat(body);
}
測試:
x = parse_with_fns(stringify_with_fns({a: function() {var x=1;}}))
x.a
> function anonymous() {var x=1;}
但請注意,由於new Function
創建的函數全部在全局範圍內,所以它們將失去其封閉範圍和閉包。
剩下的唯一問題是這是否有用。我想這可能是針對小型實用功能。
將概念擴展到序列化/反序列化正則表達式或日期對象作爲練習。
有趣...但我無法想象有一種方法可以實際獲取函數體中的代碼作爲字符串。但我可能是錯的,如果有辦法,那就太棒了:) – 2010-11-27 20:36:55
咦?有這樣一種方式:myfunc.toString()調用沒有出現:P https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/toString問題是沒有得到函數的代碼,而是優雅地用它代替字段的值,而不必破壞JSON解析器。 – dpq 2010-11-27 20:45:28