JavaScript 中 eval 的替代方案是什么?

发布于 2024-08-16 22:33:07 字数 622 浏览 2 评论 0 原文

我有一些代码看起来像这样:

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    this.i = [];
    for (var i=1,j=0 ;i<9;i++) {
        var k = eval("i"+i);
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

FireBug profiler 声称第二长的函数是 eval(),占用了近 6% 的运行时间。

每个人都说 eval 是邪恶的(就像 bad 一样)而且很慢(正如我发现的),但我真的不能做任何其他事情 - 服务器只是将数据从数据库中取出并推送到浏览器。

我有什么替代方案?我可以做与我在服务器上所做的相同的事情,但这只会将负担转移到更高的链条上。我无法更改数据库布局,因为所有内容都与这 8 个变量挂钩,并且是一项艰巨的任务。

I have a little bit of code that looks just like this:

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    this.i = [];
    for (var i=1,j=0 ;i<9;i++) {
        var k = eval("i"+i);
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

FireBug profiler claims that second longest function is eval(), taking up to nearly 6% of the run time.

Everyone says eval is EVIL (as in bad) and slow (as I have found), but I can't really do anything else - the server simply pulls the data out the database and pushes to the browser.

What alternatives do I have? I could do the same as I am doing here on the server but that just shifts the burden higher up the chain. I can't change the database layout since everything hooks into those 8 variables and is a massive undertaking.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

汹涌人海 2024-08-23 22:33:08
  1. 使用一个参数(一个数组)调用函数
  2. 使用 arguments 对象
  1. Call the function with one argument — an Array
  2. Use the arguments object
唐婉 2024-08-23 22:33:08

将数组而不是单个参数传递给函数的一种替代方法是:

StrippedExample([3, 1, 4, 1, 5, 9, 2, 6])

那么您的代码将是:

function StrippedExample(inArray) {
    this.i = [];
    for (var i=0,j=0 ;i<inArray.length;i++) {
        var k = inArray[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

如果您确实需要传递单独的参数,您可以使用 arguments 数组,这是一个行为类似于数组的对象(尽管它不是真正的数组;不是所有数组方法都对其起作用),公开已传递给函数的所有参数;在这种情况下甚至不需要声明它们,但是包含注释以指示您期望代码的用户使用哪种类型的参数是一种很好的形式:

function StrippedExample(/*i1, i2, i3, i4, i5, i6, i7, i8*/) {
    this.i = [];
    for (var i=0,j=0 ;i<arguments.length;i++) {
        var k = arguments[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

如果保证只有 8 个元素,那么您可以使用 < code>8 代替 inArray.lengtharguments.length;我决定在我的示例中使用更通用的版本,以防对您有帮助。

One alternative to to pass an array to your function, instead of individual arguments:

StrippedExample([3, 1, 4, 1, 5, 9, 2, 6])

Then your code would be:

function StrippedExample(inArray) {
    this.i = [];
    for (var i=0,j=0 ;i<inArray.length;i++) {
        var k = inArray[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

If you really need to pass in separate arguments, you can access them using your arguments array, which is an object that acts like an array (though it's not really; not all Array methods work on it) that exposes all arguments that have been passed in to your function; they do not even need to be declared in this case, but it's good form to include a comment indicating what sorts of arguments you are expecting for users of your code:

function StrippedExample(/*i1, i2, i3, i4, i5, i6, i7, i8*/) {
    this.i = [];
    for (var i=0,j=0 ;i<arguments.length;i++) {
        var k = arguments[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

If you're guaranteed to only have 8 elements, then you could use 8 in place of inArray.length or arguments.length; I decided to use the more general version in my examples in case that was helpful to you.

甜心 2024-08-23 22:33:08

该代码应该使用每个 Javascript 函数都可以访问的 arguments 数组。

这并不是说 eval邪恶(它是在 Lisp 中,所以它一定是),它只是一个 hack 的标志 - 你需要一些东西来工作,而你强迫它。它向我尖叫着“作者放弃了良好的编程设计,只是找到了一些有用的东西”。

This code should be made to use the arguments array that every Javascript function has access to.

It's not that eval is evil (it's in Lisp, so it must be good) it's simply a sign of a hack - you need something to work and you forced it. It screams out to me "The author gave up on good programming design and just found something that worked".

提笔书几行 2024-08-23 22:33:08
function StrippedExample() {

    this.i = [];
    for (var i=1,j=0 ;i<arguments.length;i++) {
        var k = arguments[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}
function StrippedExample() {

    this.i = [];
    for (var i=1,j=0 ;i<arguments.length;i++) {
        var k = arguments[i];
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}
ˉ厌 2024-08-23 22:33:08
  1. 简短的回答:
StrippedExample=(...a)=>a.filter(i=>i>0);

根本不需要使用 eval 来处理参数。

  1. 初始代码和大多数建议的解决方案不会以传统方式返回结果。
  1. Short answer:
StrippedExample=(...a)=>a.filter(i=>i>0);

no need use eval for work with arguments at all.

  1. Initial code and most proposed solutions doesn't return result by traditional way.
叫思念不要吵 2024-08-23 22:33:08

鉴于变量的数量是固定的,您可以手动构建它们的数组并循环遍历它。但是,如果您有可变数量的参数,则将变量作为数组传递给函数的一种方法是:

var args = Array.prototype.slice.call(arguments.callee.caller.arguments);

您的函数将如下所示:

function StrippedExample() {
    var args = Array.prototype.slice.call(arguments.callee.caller.arguments);
    for(var i in args) {
        if (args[i] > 0) {
            this.i[j++] = args[i];
        }
    }
}

Given that there is a fixed amount of variables, you can build an array of them manually and loop through it. But if you have a variable amount of arguments, one way to get the variables passed to the function as an array is:

var args = Array.prototype.slice.call(arguments.callee.caller.arguments);

And your function would look like this:

function StrippedExample() {
    var args = Array.prototype.slice.call(arguments.callee.caller.arguments);
    for(var i in args) {
        if (args[i] > 0) {
            this.i[j++] = args[i];
        }
    }
}
戴着白色围巾的女孩 2024-08-23 22:33:08

一定要尝试将此作为替代品。
我一直在寻找这个答案并来到这篇文章。
我阅读了开发人员文档,这在我的应用程序中作为直接替代

var func1 = "stringtxt" + object  + "stringtxt";


instead of --->    eval(func1);    --> use -->   Function(func1)(); 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Never_use_eval

definitely try this as a drop in replacement.
I was looking for this answer and came to this post.
I read the developer doc and this worked as a direct replacement in my application

var func1 = "stringtxt" + object  + "stringtxt";


instead of --->    eval(func1);    --> use -->   Function(func1)(); 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Never_use_eval!

暖伴 2024-08-23 22:33:08

您还可以使用 setTimeout 运行字符串表达式。它的工作原理与 Function 对象相同。

let a=10;
window.a=100;
window.b=1;
setTimeout("let c=1000;console.log(a,b,c)");//10,1,1000

You can also run string expressions with setTimeout. It works the same as the Function object.

let a=10;
window.a=100;
window.b=1;
setTimeout("let c=1000;console.log(a,b,c)");//10,1,1000
趴在窗边数星星i 2024-08-23 22:33:07
function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    var args = [i1, i2, i3, i4, i5, i6, i7, i8]; // put values in an array
    this.i = [];
    for (var i=0,j=0 ;i<8;i++) { // now i goes from 0-7 also
        var k = args[i]; // get values out
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

上面的代码可以进一步简化,我只是做了最小的改变来摆脱eval。你可以去掉j,例如:

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    var args = [i1, i2, i3, i4, i5, i6, i7, i8];
    this.i = [];
    for (var i = 0; i < args.length; i++) {
        var k = args[i];
        if (k > 0) { this.i.push(k); }
    }
}

是等价的。或者,使用内置的 arguments 对象(以避免参数列表出现在两个位置):

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    this.i = [];
    for (var i = 1; i < arguments.length; i++) {
        var k = arguments[i];
        if (k > 0) { this.i.push(k); }
    }
}

即使您没有过滤列表,您也不想执行类似 的操作>this.i = Arguments 因为 arguments 不是真正的数组;它有一个您不需要的 callee 属性,并且缺少 i 中可能需要的一些数组方法。正如其他人指出的那样,如果您想快速将 arguments 对象转换为数组,可以使用以下表达式来实现:

Array.prototype.slice.call(arguments)

您可以使用它来代替 var args = [i1, i2 ... 行上面。

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    var args = [i1, i2, i3, i4, i5, i6, i7, i8]; // put values in an array
    this.i = [];
    for (var i=0,j=0 ;i<8;i++) { // now i goes from 0-7 also
        var k = args[i]; // get values out
        if (k > 0) {
            this.i[j++] = k;
        }
    }
}

The above code can be simplified further, I just made the minimal change to get rid of eval. You can get rid of j, for example:

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    var args = [i1, i2, i3, i4, i5, i6, i7, i8];
    this.i = [];
    for (var i = 0; i < args.length; i++) {
        var k = args[i];
        if (k > 0) { this.i.push(k); }
    }
}

is equivalent. Or, to use the built-in arguments object (to avoid having your parameter list in two places):

function StrippedExample(i1, i2, i3, i4, i5, i6, i7, i8) {
    this.i = [];
    for (var i = 1; i < arguments.length; i++) {
        var k = arguments[i];
        if (k > 0) { this.i.push(k); }
    }
}

Even if you weren't filtering the list, you don't want to do something like this.i = arguments because arguments is not a real Array; it has a callee property that you don't need and is missing some array methods that you might need in i. As others have pointed out, if you want to quickly convert the arguments object into an array, you can do so with this expression:

Array.prototype.slice.call(arguments)

You could use that instead of the var args = [i1, i2 ... lines above.

沉溺在你眼里的海 2024-08-23 22:33:07

评估替代方案:

let exp = '1 + 1'
let x = new Function('return ' + exp)()
console.log(x)

Eval alternative:

let exp = '1 + 1'
let x = new Function('return ' + exp)()
console.log(x)
谈下烟灰 2024-08-23 22:33:07

您只需从函数的 8 个参数创建一个数组,删除小于或等于 0 的参数。

以下代码是等效的,它适用于任意数量的参数:

function StrippedExample() {
  var args = [];

  for (var i = 0; i < arguments.length; i++) {
    if (arguments[i] > 0) {
      args.push(arguments[i]);
    }
  }
  //...
}

You are simply making an array from your function 8 arguments, removing the ones that are less than or equal to zero.

The following code is equivalent, and it will work for any arbitrary number of arguments:

function StrippedExample() {
  var args = [];

  for (var i = 0; i < arguments.length; i++) {
    if (arguments[i] > 0) {
      args.push(arguments[i]);
    }
  }
  //...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文