什么是正确的“;串行化”;javascript中的函数以供以后使用

What is the correct way to "serialize" functions in javascript for later use

本文关键字:函数 javascript 什么      更新时间:2024-03-23

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

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做任何事情,他们不能更容易地用Chrome调试器做任何事情。任何人都可以在客户端上运行他们想要的任何代码,这取决于你的服务器来决定如何处理它接收到的内容。客户一开始就没有安全可言。。。

更改对象的原型是我的一半想法。

你的图书馆就像一样

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

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

theObj.__proto__ = library["myObj"];

这样你就可以执行

theObj.function(...);

jsfiddle示例(这是粗糙的!)。此外,要小心proto,它已被弃用(1)(2)

至于序列化函数,你能使用一个脚本标签来获取它们吗?这个标签指向服务器端的某个东西,从数据库中抓取它们并返回js?在渲染页面时(在脚本块中)只将它们内联吗?或者,如果所有其他操作都失败了,那么eval应该可以工作,只要您知道存储在数据库中的函数是干净和安全的。

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

然而,如果你想以任何方式做到这一点,你可以简单地用.toJSON方法扩展Function的原型。

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

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

在大多数情况下,这通常不是一个好主意。很少有情况下你想这样做,即使这样,也可能有更好的方法。

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

您使用它所做的一切都很好。然而,如果我是你,为了可读性和简洁性,我宁愿在外部创建函数,并将其分配给你的对象键。

这里不需要eval。相反,只要你想访问存储的功能-,就可以这样做

library.myObj.function()

  • 你尽你最大的努力参数化你的函数,这样你尽可能少的类型
  • 将它们存储在服务器上的各个JS文件中,然后按名称动态加载所需的文件
  • 在JSON中,只存储包含所需函数的文件名。当然,您将缓存已经加载的文件,以便在服务器上轻松操作

只有我的两美分。

你只能用require调用来串行化整个文件。如果你这样做,你可以创建一个模块,导出和module.exports,用一个围绕它的函数来评估文件,并从中获取module.export。

它并不完全安全,但为此,你需要使用VM2和价值审查(我一直在研究)之类的东西,以避免他们调用eval()并拥有你的机器或整个网络。