繁体   English   中英

在javascript中“序列化”函数以供以后使用的正确方法是什么

[英]What is the correct way to “serialize” functions in javascript for later use

我有一个对象的“库”,我想从数据库中动态加载。 每个对象都有自己的特殊函数,这些函数在特定时间根据对象类型调用。 理想情况下,我希望能够做到这一点,尽管有人指出这不起作用:

library = {
  "myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}

字符串"myObj"在我的程序中传递了很多,但我只需要一次访问对象的某些值,在某些情况下,需要运行一个特定的函数。 问题是我正在查看数百个,最终成千上万个可能存在不同功能的潜在对象。

存储要像这样调用的函数的“正确”方法是什么。 我知道在执行期间调用eval会非常不安全,从而实现xss攻击等等。 我真的想避免大量的switch语句或额外函数的膨胀加载。 我也希望解决方案尽可能简洁。

这可能不是第一次出现。 ; /

谢谢你的帮助。

在将其作为字符串加载后,只需使用eval重新创建该函数。 因此,如果您从JSON反序列化对象myObj ,并且您有一个属性:

myObj = {
    ....
    function: "function() { ... }"
}

你可以很容易地把它变成一个真正的功能:

eval("myObj.func = " + myObj.func);

http://jsfiddle.net/kceTr/

哦 - 我不确定这是否是编辑或我之前错过了 - 但重新:eval。

Eval是一种工具。 您希望将函数存储在数据库中。 如果你必须“eval”把它变成代码,或者还有其他一些神奇的方法可以做到这一点,那真的没什么区别:如果有人可以改变数据库中的数据,那么他们就可以改变一个功能。

如果您需要存储函数,那么eval就是您的工具。 它本质上并不“坏”,它很糟糕,因为它容易被滥用。 无论您使用得好还是由您自己决定。

请记住,客户端上运行的任何内容仍然只在客户端上运行。 没有任何恶意的人可以使用eval,他们无法轻松地使用Chrome调试器。 任何人都可以随时在客户端上运行他们想要的任何代码,由服务器来决定如何处理它收到的内容。 首先,客户端没什么安全的......

改变对象的原型是我想到的一半。

你的图书馆就像

library = {
  "myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}

你有一个对象(让我们称之为theObj ),你知道它是一个myObj (由于字符串可能是?属性?)

theObj.__proto__ = library["myObj"];

那样你就可以执行了

theObj.function(...);

jsfiddle例子(这很粗糙 !)。 另外,小心proto ,它已被弃用( 1 )( 2

至于序列化这些函数,你是否可以使用一个脚本标记来指向某些服务器端,这些服务器从数据库中剔除它们并返回js? 只需在渲染页面时将它们包含在内(在脚本块中)? 或者,如果所有其他方法都失败了,只要您知道存储在数据库中的函数是干净且安全的,那么eval应该可以正常工作。

更好的方法可能是在“睡眠”时序列化对象的属性,并通过使用定义的适当方法将其属性重新附加到对象的新实例来“唤醒”对象。

你正在做什么就好了。 但是,如果我是你,为了可读性和整洁,我宁愿在外面创建函数,只需将它分配给您的对象键。

你这里不需要eval。 相反,只要您想要访问存储的函数,就这样做 -

library.myObj.function()

  • 您可以尽力参数化您的功能,以便尽可能减少类型。
  • 将它们存储在服务器上的各个JS文件中,然后按名称动态加载所需的文件。
  • 在JSON中,仅存储包含所需功能的文件的名称。 当然,您将缓存已加载的文件,以便在服务器上轻松实现。

只是我的两分钱。

您只能通过其中的require调用来真正序列化整个文件。 如果你这样做,你可以创建一个模块,exports和module.exports,用它周围的函数评估文件,并从中获取module.exports。

它并不完全安全,但为此您需要使用VM2价值审查 (我一直在努力),以避免他们调用eval()并拥有您的机器或整个网络。

没有正确的方法来做到这一点,因为它通常不是一个好主意。

但是,如果你想要这样做,你可以简单地用.toJSON方法扩展Function的原型。

Function.prototype.toJSON = function(){ return this.toString(); }

然后你可以简单地使用JSON.stringify,函数将被序列化为字符串。

在大多数情况下,它通常不是一个好主意。 在很少的情况下你想要这样做,即便如此,也许有更好的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM