熟悉前端的童鞋都知道,JSON格式是无法保存函数格式的。
然而,JSON提供了stringify和parse的一些特殊机制,可以实现这一需求。
思路:在将对象转换成字符串时,将函数参数和函数体分别保存成字符串。在获取json转换回对象时,将其还原为方法。
首先,我们需要准备两个方法,用来获取函数的参数和函数体。
// 获得函数参数
function getFunctionArgsName(func) {
var args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1]
return args
.split(',')
.map(function (arg) {
return arg.replace(/\/\*.*\*\//, '').trim()
})
.filter(function (_args) {
//确保没有undefineds
return _args
})
}
// 获得函数体
function getFunctionBody(func) {
var args = func.toString().match(/(function\s.*?\(([^)]*)\))/)[1]
var funBody = func.toString().replace(args, '')
funBody = funBody.replace(/^[\s]*\{/, '')
funBody = funBody.replace(/\}[\s]*$/, '')
return funBody
}
假设有这样的对象
var func = function(a, b) {
return a + b;
}
var foo = {
name: 'mike',
func: func
}
console.log(JSON.stringify(foo))
当使用JSON.stringify转换后,func函数会丢失。然而,JSON.stringify还有一个特性,当对象中包含有toJSON方法时,会调用该方法进行序列化。如此,我们就可以在函数赋值给对象前给函数增加一个方法。
var func = function(a, b) {
return a + b;
}
func.toJSON = function() {
return JSON.stringify({
args: getFunctionArgsName(func),
body: getFunctionBody(func)
})
}
var foo = {
name: 'mike',
func: func
}
console.log(JSON.stringify(foo))
打印结果
{"name":"mike","func":"{\"args\":[\"a\",\"b\"],\"body\":\"\\n return a + b\\n \"}"}
在用JSON.parse 转换对象时,会获得一个对函数的描述对象,可通过JSON.parse的第二个参数(过滤函数), 对其进行特殊处理
var jsonString = JSON.stringify(foo);
var parseObj = JSON.parse(jsonString, function (key, value) {
if (key === 'func') {
const fnobj = JSON.parse(value)
return new Function(...fnobj.args, fnobj.body)
} else {
return value
}
})
console.log(parseObj.func(1,2))
完整代码如下:
<body>
<script>
function getFunctionArgsName(func) {
var args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1]
return args
.split(',')
.map(function (arg) {
return arg.replace(/\/\*.*\*\//, '').trim()
})
.filter(function (_args) {
//确保没有undefineds
return _args
})
}
function getFunctionBody(func) {
var args = func.toString().match(/(function\s.*?\(([^)]*)\))/)[1]
var funBody = func.toString().replace(args, '')
funBody = funBody.replace(/^[\s]*\{/, '')
funBody = funBody.replace(/\}[\s]*$/, '')
return funBody
}
var func = function (a, b) {
return a + b
}
func.toJSON = function () {
return JSON.stringify({
args: getFunctionArgsName(func),
body: getFunctionBody(func)
})
}
var foo = {
name: 'mike',
func: func
}
console.log(JSON.stringify(foo))
var jsonString = JSON.stringify(foo)
var parseObj = JSON.parse(jsonString, function (key, value) {
if (key === 'func') {
const fnobj = JSON.parse(value)
return new Function(...fnobj.args, fnobj.body)
} else {
return value
}
})
console.log(parseObj.func(1, 2))
</script>
</body>
打印结果
{"name":"mike","func":"{\"args\":[\"a\",\"b\"],\"body\":\"\\n return a + b\\n \"}"}
3
网友评论