2012-04-27 5 views
0

У меня есть имя метода в виде строки в JavaScript переменной, и я хотел бы получить результат ее вызова переменной:Избавление от Eval

var myMethod = "methodToBeCalled"; 
var result; 
eval("result = "+myMethod+"();") 

Это работает, и нет никаких проблем. Но этот код неприемлем для компилятора Google Closure. Как я могу изменить его для работы с ним? Благодаря!

EDIT:

Кажется, что предлагаемые решения не работает, когда имя метода внутри какого-либо объекта, например:

var myFunction = function() { return "foo!" } 
var myObject = { 
    itsMethod: function() { return "foo!" } 
}; 
... 
var fstMethodToCall = "myFunction" 
var sndMethodToCall = "myObject.itsMethod"; 
... 
window[fstMethodToCall](); // foo! 
window[sndMethodToCall](); // undefined 

ответ

2

Предполагая, что вы не в гнездовой рамки некоторых вид, попробуйте:

var result = window['methodToBeCalled'](); 

или

var myMethod = 'methodToBeCalled'; 
var result = window[myMethod](); 

Чтобы выполнить произвольную функцию произвольной глубины на основе строки спецификации, а не выполнение Eval:

var SomeObject = { 
    level1: { 
     level2: { 
      someFunc: function() { 
       console.log('hello'); 
      } 
     } 
    } 
}; 

var target = 'SomeObject.level1.level2.someFunc'; 

var obj; 
var split = target.split('.'); 
for (var i = 0; i < split.length; i++) { 
    obj = (obj || window)[split[i]]; 
} 

obj(); 
+0

А как насчет окна [ "SomeObject.itsMethod"] - похоже, что это не работает? –

+0

@ Vojtěch Предполагая, что 'SomeObject.itsMethod' является строковым именем для функции верхнего уровня, попробуйте окно [SomeObject.itsMethod](); – Matt

+0

Я имел в виду нечто вроде 'var Object = {itsMethod: function() {...}}; var call = "Object.itsMethod"; window [call](); ' –

2

Вы можете использовать индексатор обозначение:

result = window[myMethod](); 
1

замыкание Компилятор не запрещает " eval ', вы можете продолжать использовать его, если найдете его удобным, но вы должны понимать, что компилятор не пытается понять, что происходит в вашем заявлении eval, и предполагает, что ваш eval является «безопасным»:

function f(x, y) { 
    alert(eval("y")); // fails: hidden reference to "y" 
    alert(eval('"'+x+'"')); // might be valid 
} 
f('me', 'you'); 

Когда компилятор оптимизирует эту функцию, он пытается удалить «y» и переименовал параметр останова. Это будет первая ошибка eval, поскольку «y» больше не существует. Второй eval исправит отображение предупреждения «я».

Таким образом, с помощью простых оптимизаций вы можете использовать eval для ссылки на глобальные переменные и свойства объекта, поскольку они не переименованы или не удалены (но не локальные).

С оптимизацией ADVANCED это немного сложнее, поскольку компилятор пытается удалить и переименовать глобальные, а также локальные переменные. Поэтому вам нужно экспортировать значения, которые необходимо сохранить. Это также верно, если вы используете строку, чтобы попытаться сослаться на имя другими способами:

var methodName = "myMethod"; 
(window[methodName])() 

или

var methodName = "myMethod"; 
eval(methodName+"()") 

компилятор просто не пытается определить, является ли «имяМетод» является ссылкой к функции. Вот просто пример ADVANCED экспорта режима:

window['myMethod'] = myMethod; 

Назначение делает две вещи: она сохраняет функцию MyMethod, если бы в противном случае быть удалены, и это дает ему фиксированное имя, присвоив его свойству с помощью строка. Если вам нужно ссылаться на локальные значения, вам нужно немного сложнее и использовать конструктор Function.Определение "ф" из моего первого примера, который может Eval местных жителей:

var f = new Function("x", "y", "alert(eval('y')); alert(eval('\"' + x + '\"'));"); 

Вы можете найти эту страницу полезной:

https://developers.google.com/closure/compiler/docs/limitations

Смежные вопросы