Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/90.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaScript中序列化函数?_Javascript_Html_Serialization_Local Storage - Fatal编程技术网

如何在JavaScript中序列化函数?

如何在JavaScript中序列化函数?,javascript,html,serialization,local-storage,Javascript,Html,Serialization,Local Storage,例如,假设我有一个定义如下的函数: function foo() { return "Hello, serialized world!"; } 我希望能够序列化该函数并使用localStorage存储它。我该怎么做呢?大多数浏览器(Chrome、Safari、Firefox,可能还有其他浏览器)都会从.toString()方法返回函数定义: > function foo() { return 42; } > foo.toString() "function foo() { re

例如,假设我有一个定义如下的函数:

function foo() {
  return "Hello, serialized world!";
}
我希望能够序列化该函数并使用
localStorage
存储它。我该怎么做呢?

大多数浏览器(Chrome、Safari、Firefox,可能还有其他浏览器)都会从
.toString()方法返回函数定义:

> function foo() { return 42; }
> foo.toString()
"function foo() { return 42; }"
只是要小心,因为本机函数不会正确序列化。例如:

> alert.toString()
"function alert() { [native code] }"
函数foo(){
警报(“本机函数”);
返回“你好,连载世界!”;
}
连载
var-storedFunction=foo.toString();
反序列化
var actualFunction=new函数('return'+foo.toString())()
解释 toString()将是函数foo的字符串版本

"function foo() { ... return 'Hello, serialised world!';}"
但是
新函数
采用函数体,而不是函数本身

所以我们可以创建一个函数,返回这个函数,并将它赋给某个变量

"return function foo() { ... return 'Hello, serialised world!';}"
现在,当我们将这个字符串传递给构造函数时,我们得到一个函数,并立即执行它以返回原始函数。:)


这与w(3)不同,w(3)仍然记得添加3。

我做这个回答是为了解决现有答案中的一些相当大的缺陷:
.toString()
/
eval()
新函数()
如果你的函数使用或命名参数(
函数(命名,arg){}
),它们本身根本不起作用,分别

使用下面的,您需要做的就是像往常一样调用函数,然后使用
函数

以下内容不适用于简明函数(
hello=>'there'
),但对于标准ES5 fat函数,它将按定义返回它,当然,闭包除外


Function.prototype.toJSON=Function(){
var parts=this
.toString()
.match(/^\s*函数[^(]*\([^)]*)\)\s*{(.*)\s*$/)
;
if(parts==null)
抛出“不支持函数形式”;
返回[
“window.Function”,
零件[1].trim().split(/\s*,\s*/),
第[2]部
];
};
Function.deserialise=函数(键、数据){
返回(数组的数据实例和数据[0]=“window.Function”)?
新建(Function.bind.apply(Function[Function].concat(数据[1],[data[2]]):
数据
;
};

看一看

最简单的是:

var test=function(where){return'hello'+where;};
test=JSON.parse(JSON.stringify(test),Function.deserialise);
console.log(test('there'));
//打印“你好”

更有用的是,您可以序列化包含函数的整个对象,并将它们拉回来

测试={
答:2,,
运行:函数(x,y,z){返回这个.a+x+y+z;}
};
var serialised=JSON.stringify(测试);
控制台日志(序列化);
控制台日志(序列化的类型);
var tester=JSON.parse(序列化、函数反序列化);
console.log(tester.run(3,4,5));
产出:

{“a”:2,“run”:[“window.Function”,[“x”,“y”,“z”],“returnthis.a+x+y+z;”
一串
14

我没有测试旧版IE,但它可以在IE11、FF、Chrome和Edge上运行

注意,函数的属性丢失,如果您使用该属性,那么您真的无能为力。

您可以轻松地将其更改为不使用原型,但如果您需要的话,您可以这样做。

如果您需要一种在ES6中串行化的方法,我已经编写了一个串行化器,它可以使一切正常工作

您只需像往常一样对包含函数的函数或对象调用
JSON.stringify()
,然后调用
function.deserialise
on,魔术就开始了

显然,您不应该期望闭包工作,它毕竟是串行化的,但默认值、解构、
参数
成员函数都将被保留。
如果您只使用ES5符号,请使用。这真的是一个超越


在Chrome/Firefox/Edge中工作。
Bellow是演示的输出;一些函数,序列化字符串,然后调用反序列化后创建的新函数

测试={
//制作函数
run:function name(x,y,z){返回这个.a+x+y+z;},
a:2
};
//序列化它,看看它是什么样子
test=JSON.stringify(test)/{“run”:[“window.Function”,[“x”,“y”,“z”],“returnthis.a+x+y+z;”],“a”:2}
test=JSON.parse(test,Function.deserialise)
//看看这个是否有效,应该是2+3+4+5:14
test.run(3,4,5)//14
测试=()=>7
test=JSON.stringify(test)/[“window.Function”、[“”]、“return 7”]
JSON.parse(test,Function.deserialise)(//7
测试=材料=>material.length
test=JSON.stringify(test)/[“window.Function”、[“material”]、“return material.length”]
JSON.parse(test,Function.deserialise)([1,2,3])//3
测试=([a,b]=[1,2],{x:c}={x:a+b})=>a+b+c
test=JSON.stringify(test)/[“window.Function”、[“[a,b]=[1,2]”、“{x:c}={x:a+b}”]、“return a+b+c”]
JSON.parse(test,Function.deserialise)([3,4])//14
班鲍勃{
构造函数(bob){this.bob=bob;}
//没有'function'关键字的fat函数!!
test(){返回this.bob;}
toJSON(){return{bob:this.bob,test:this.test}
}
测试=新鲍勃(7);
test.test()//7.
test=JSON.stringify(test)//{“bob”:7,“test”:[“window.Function”,[“”],“returnthis.bob;”]}
test=JSON.parse(test,Function.deserialise);
test.test()//7.

最后是魔法

Function.deserialise=函数(键,数据){
返回(数组的数据实例和数据[0]=“window.Function”)?
新建(Function.bind.apply(Function[Function].concat(数据[1],[data[2]]):
数据
;
};
Function.prototype.toJSON=Function(){
变量空白=/\s/;
变量对=/\(\)\[\]\{\}/;
var args=新数组();
瓦尔斯特林
w = (function(x){
    return function(y){ 
        return x+y; 
    };
});""+w returns "function(x){
    return function(y){
        return x+y;
    };
}" but ""+w(3) returns "function(y){
    return x+y; 
}"