函数在JSON中如何保存?

熟悉前端的童鞋都知道,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

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):