是否可以在不使用 eval() 的情况下以编程方式从字符串或其他技术定义函数

Is it possible to programmatically define a function from a string or some other technique without using eval()?

本文关键字:字符串 方式 编程 其他 函数 定义 技术 情况下 eval 是否      更新时间:2023-09-26

我正在为需要构造未知长度的嵌套回调函数的情况进行编码。它是创建一个有序的动画队列,以在未知的#位置上移动元素。

例如,输出看起来像这样,其中嵌套了 X"完整"回调:

$('#element').animate(css, { complete: function () {
          $('#element').animate(css, { complete: function () {
              // more nested calls inside
          }
});

现在我正在将这些函数生成为字符串,然后在完成后将其提供给新的 Function():

myFunc = new Function(generatedFuncString);

内容是受信任的,但这仍然使用 eval(),这会产生负面的性能影响。我只是想知道是否有另一种/更好的方法?

编辑:我这样做的原因是因为我有一组非常复杂的动画要执行,并且正在jQuery动画队列之外工作。如果有人对如何完成这样的情况有更好的建议,那将是有帮助的......

想象一下一颗棒球钻石,第一名是跑步者(A),第三名是跑步者(B)。在一个动画捆绑包中,我想将跑步者 A 动画化到 3rd(停在中间的第 2 位,前进 2 个),将跑步者 B 动画化到 HOME(前进 1 个)。

我必须用"queue:false"启动初始前进,以便跑步者 A 和 B 同时移动到他们的第一个垒(跑步者 A 到第二垒,跑步者 B 到家)。

当运行器 A 完成移动到第 2 个时,我想将他移动到第 3 个(因此在语法上构造一个带有嵌套回调的 animate() 调用,以确保保留此顺序)。

我通过字符串构造函数的原因是因为我知道最里面的回调首先是什么,然后从那里递归构造 1 个或多个外层回调。我无法找到一种方法来做到这一点,方法是将函数作为对象使用并保持所有引用。

请记住,这是一个简单的例子。想象一下这样一种情况,基地被加载,我需要制作一个大满贯的动画(所有 4 名跑步者都绕着所有基地转,来自家乡的跑步者需要做 3 次停止才能跑回家)。等等等等。

回答您在标题中提出的问题: 您可以通过 evalnew Function 以及插入带有所需文本的 script 元素从字符串创建函数。但这一切都归结为同一件事:启动JavaScript解析器并创建函数。

但我认为你想要的不是嵌套,而是链接。生成数组中动画的列表,并使用 animate 回调调用数组中的下一个动画。这样:

var animations = [
    /* css for first animation */,
    /* css for second animation */,
    /* etc. */
];
var index = 0;
function runAnimation() {
    if (index < animations.length) {
        $("#element").animate(animations[index++], runAnimation);
    }
}

当然,您将动态构建数组。


Gdoron在评论中指出,如果你所有的动画都在同一个元素上,它可以更简单:

var animations = [
    /* css for first animation */,
    /* css for second animation */,
    /* etc. */
];
var index = 0;
for (index = 0; index < animations.length; ++index) {
    $("#element").animate(animations[index]);
}

。因为当您对同一元素多次调用animate时,默认情况下动画会排队(queue选项默认为 true ;遗憾的是,文档似乎没有这么说)。我上面的代码示例不依赖于队列,因此理论上数组中的每个条目都可以是一个对象,该对象具有用于选择器的属性,用于对要进行动画处理的元素和要应用的 css。但是,如果它都是一个元素,你可以只使用直线循环。

相关文章: