Каковы альтернативы 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 переменных и является огромным делом.
Ответы
Ответ 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
- Короткий ответ:
StrippedExample=(...a)=>a.filter(i=>i>0);
нет необходимости использовать eval для работы с аргументами вообще.
- Исходный код и большинство предлагаемых решений не возвращает результат традиционным способом.