JavaScript中的eval有哪些替代方案?

问题描述 投票:13回答:9

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

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%。

Everyone says eval is EVIL(和坏的一样)和慢(我发现),但我不能做任何其他事情 - 服务器只是将数据从数据库中拉出并推送到浏览器。

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

javascript eval
9个回答
14
投票
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 ...线。


7
投票

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

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

function StrippedExample() {
  var args = [];

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

5
投票
  1. 使用一个参数调用该函数 - 一个数组
  2. 使用arguments对象

4
投票

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

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个元素,那么你可以使用8代替inArray.lengtharguments.length;我决定在我的示例中使用更通用的版本,以防对您有所帮助。


1
投票

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

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


1
投票
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;
        }
    }
}

1
投票

Eval替代方案:

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

0
投票

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

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];
        }
    }
}

0
投票
  1. 简短回答:
StrippedExample=(...a)=>a.filter(i=>i>0);

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

  1. 初始代码和大多数建议的解决方案不会以传统方式返回结果。
© www.soinside.com 2019 - 2024. All rights reserved.