Каковы альтернативы eval в JavaScript? - программирование
Подтвердить что ты не робот

Каковы альтернативы eval в JavaScript?

У меня есть немного кода, который выглядит примерно так:

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 утверждает, что второй самой длинной функцией является eval(), занимая почти 6% времени выполнения.

Все говорят, что eval - это EVIL (как в плохом) и медленный (как я нашел), но я не могу ничего сделать - сервер просто тянет данные из базы данных и подталкиваются к браузеру.

Какие альтернативы у меня есть? Я мог бы сделать то же самое, что и здесь, на сервере, но это просто сдвигает нагрузку выше цепи. Я не могу изменить компоновку базы данных, так как все перехватывает эти 8 переменных и является огромным делом.

4b9b3361

Ответ 1

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 ... выше.

Ответ 2

Вы просто делаете массив из своих аргументов 8, удаляя те, которые меньше или равны нулю.

Следующий код эквивалентен, и он будет работать для любого произвольного количества аргументов:

function StrippedExample() {
  var args = [];

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

Ответ 3

  • Вызов функции с одним аргументом - Массив
  • Используйте 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, который является объектом, который действует как массив (хотя это не так, не все методы Array работают над ним), который предоставляет все аргументы, которые были переданы вашей функции; их даже не нужно объявлять в этом случае, но в хорошей форме включить комментарий, указывающий, какие аргументы вы ожидаете для пользователей вашего кода:

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.length или arguments.length; Я решил использовать более общую версию в своих примерах в случае, если это было полезно для вас.

Ответ 5

Этот код должен быть использован для использования массива arguments, к которому имеет доступ каждая функция Javascript.

Это не то, что eval зло (оно в Lisp, поэтому оно должно быть хорошим), это просто признак взлома - вам нужно что-то работать, и вы его заставили. Он кричит мне: "Автор отказался от хорошего программирования и просто нашел что-то, что сработало".

Ответ 6

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

Ответ 7

Альтернатива Eval:

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

Ответ 8

Учитывая, что существует фиксированное количество переменных, вы можете построить массив из них вручную и выполнить цикл через него. Но если у вас есть переменное количество аргументов, один из способов получить переменные, переданные функции в качестве массива:

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

Ответ 9

  1. Короткий ответ:
StrippedExample=(...a)=>a.filter(i=>i>0);

нет необходимости использовать eval для работы с аргументами вообще.

  1. Исходный код и большинство предлагаемых решений не возвращает результат традиционным способом.