我有一个对象的“库”,我想从数据库中动态加载。每个对象都有自己的特殊函数,这些函数在特定时间根据对象类型调用。理想情况下,我希望能够做到这一点,尽管有人指出这不起作用:
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
字符串"myObj"
在我的程序中传递了很多,但我只需要一次访问对象的某些值,在某些情况下,需要运行一个特定的函数。问题在于,我正在研究数百个,最终成千上万个可能存在不同功能的潜在对象。
存储要像这样调用的函数的“正确”方法是什么。我知道在执行期间调用eval会非常不安全,从而实现xss攻击等等。我真的想避免大量的switch语句或额外函数的膨胀加载。我也希望解决方案尽可能简洁。
这可能不是第一次出现。 ; /
感谢您的帮助。
答案 0 :(得分:8)
在将其作为字符串加载后,只需使用eval重新创建该函数。因此,如果您从JSON反序列化对象myObj
,并且您有一个属性:
myObj = {
....
function: "function() { ... }"
}
你可以很容易地把它变成一个真正的功能:
eval("myObj.func = " + myObj.func);
哦 - 我不确定这是否是编辑或我之前错过了 - 但重新:eval。
Eval是一种工具。您希望将函数存储在数据库中。如果你必须“eval”把它变成代码,或者还有其他一些神奇的方法可以做到这一点,那真的没什么区别:如果有人可以改变数据库中的数据,那么他们就可以改变一个功能。
如果您需要存储功能,那么eval就是您的工具。它本质上并不“坏”,它很糟糕,因为它容易被滥用。是否使用它取决于你。
记住客户端上运行的任何内容仍然只在客户端上运行。没有任何恶意的人可以使用eval,他们无法轻松地使用Chrome调试器。任何人都可以随时在客户端上运行他们想要的任何代码,由服务器来决定如何处理它收到的内容。首先,客户端没有任何安全措施......
答案 1 :(得分:1)
改变对象的原型是我认为的一半。
你的图书馆就像
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
你有一个对象(让我们称之为theObj
),你知道它是myObj
(由于字符串可能是?属性?)
theObj.__proto__ = library["myObj"];
这样你可以执行
theObj.function(...);
jsfiddle示例(它是粗略!)。此外,请注意 proto ,不推荐使用(1)(2)
至于序列化这些函数,你是否可以使用一个脚本标记来指向某些服务器端,这些服务器从数据库中剔除它们并返回js?只需在渲染页面时将它们包含在内(在脚本块中)?或者,如果所有其他方法都失败了,只要您知道存储在数据库中的函数是干净且安全的,eval应该可以正常工作。
答案 2 :(得分:0)
更好的方法可能是在“睡眠”它时序列化对象的属性,并通过使用定义的适当方法将其属性重新附加到对象的新实例来“唤醒”对象。
答案 3 :(得分:0)
你正在做什么就好了。但是,如果我是你,为了可读性和整洁性,我宁愿在外面创建函数,只需将它分配给你的对象密钥。
这里你不需要eval。相反,只要您想要访问存储的函数,就这样做 -
library.myObj.function()
答案 4 :(得分:0)
只是我的两分钱。
答案 5 :(得分:0)
您只能真正序列化带有require
调用的整个文件。如果这样做,则可以创建一个模块,exports和module.exports,使用围绕它的函数对文件进行评估,然后将module.exports导出其中。
这并不完全安全,但是为此,您需要使用VM2和value-censorship之类的东西(我一直在努力),以避免它们调用eval()并拥有您的计算机或整个网络。
答案 6 :(得分:0)
没有正确的方法,因为通常这不是一个好主意。
但是,无论如何,只要使用 upload(event){
const id = Math.random().toString(36).substring(2);
this.ref = this.afStorage.ref(id);
this.task = this.ref.put(event.target.files[0]);
this.downloadURL = concat(
this.task.snapshotChanges().pipe(filter(() => false)),
defer(() => this.ref.getDownloadURL()),
);
}
方法扩展Function的原型即可。
.toJSON
然后您可以简单地使用JSON.stringify,函数将被序列化为字符串。
在大多数情况下,这通常不是一个好主意。在极少数情况下,您想这样做,即使那样,也可能有更好的方法。