выполнение анонимных функций, созданных с помощью JavaScript eval()

У меня есть функция и ее содержимое в виде строки.

var funcStr = "function() { alert('hello'); }";

Теперь я делаю eval(), чтобы фактически получить эту функцию в переменной.

var func = eval(funcStr);

Если я правильно помню, в Chrome и Opera просто вызов

func();

вызвал эту функцию, и предупреждение было отображено.

Но в других браузерах этого не было. ничего не произошло.

Я не хочу спорить о том, какой метод является правильным, но как я могу это сделать? Я хочу иметь возможность вызывать переменную(); для выполнения функции, хранящейся в этой переменной.


person Community    schedule 13.08.2009    source источник
comment
Мне интересно, зачем вам нужна анонимная функция, представленная в виде строкового литерала, а не просто именованная функция?   -  person Russ Cam    schedule 13.08.2009
comment
К вашему сведению: я определяю свой собственный скрипт для своего веб-приложения. Я пишу интерпретатор, и мне нужно создавать функции JS на лету, а затем создавать из них фактические исполняемые функции.   -  person    schedule 13.08.2009
comment
почему бы вам не написать интерпретатор традиционным способом?   -  person Breton    schedule 13.08.2009
comment
Я не знаю, как написать это традиционным способом.. Мне это показалось проще. Если бы вы могли подсказать мне, как это делается традиционно, было бы неплохо.   -  person    schedule 13.08.2009
comment
Попробуйте заключить функцию в круглые скобки перед передачей строки в eval. var funcStr = "( function() { alert('hello'); } )";   -  person awhie29urh2    schedule 02.07.2013


Ответы (11)


Как насчет этого?

var func = new Function('alert("hello");');

Чтобы добавить аргументы в функцию:

var func = new Function('what', 'alert("hello " + what);');
func('world'); // hello world

Обратите внимание, что функции являются объектами и могут быть назначены любой переменной, как они есть:

var func = function () { alert('hello'); };
var otherFunc = func;
func = 'funky!';

function executeSomething(something) {
    something();
}
executeSomething(otherFunc); // Alerts 'hello'
person Blixt    schedule 13.08.2009
comment
Это элегантный способ сделать это, и он работает во всех браузерах. Спасибо :) - person ; 13.08.2009

IE не может eval функционировать (предположительно по соображениям безопасности).

Лучший обходной путь — поместить функцию в массив, например:

var func = eval('[' + funcStr + ']')[0];
person SLaks    schedule 13.08.2009
comment
Да, оно может. Однако литерал функции не является оператором, поэтому вокруг него нужны круглые скобки, это чище, чем ваше решение для массива. - person Juan Mendes; 05.01.2011
comment
@Хуан: Неправильно; оно не может. Попробуйте javascript:alert(eval('( function() { return 3; } )')); - person SLaks; 05.01.2011
comment
Плохо, я предложил использовать круглые скобки вместо вашего решения массива, я не понял, что это не работает в IE - person Juan Mendes; 05.01.2011

Я понимаю, что это устарело, но это был единственный действительный результат, полученный в моих поисках Google для оценки строк анонимных функций javascript.

Наконец-то я понял, как это сделать, из сообщения в группе jquery google.

eval("false||"+data)

где данные - это строка вашей функции, например "function() {return 123;}"

До сих пор я пробовал это только в IE8 и FF8 (браузеры на моем персональном компьютере), но я считаю, что jquery использует это внутри, поэтому он должен работать практически везде.

person user319862    schedule 13.11.2011
comment
Я не понимаю, почему у всех остальных, кажется, нет этой проблемы. Это золото, спасибо! - person Shwouchk; 22.08.2017
comment
Мы можем сделать это и таким образом eval('!1||'+funcBody); - person Bharata; 29.01.2019

Пытаться

var funcStr = "var func = function() { alert('hello'); }";

eval(funcStr);

func();
person David Henderson    schedule 13.08.2009
comment
эй, спасибо, это сработало! Но это выглядит немного странно, чтобы сделать это таким образом: D. - person ; 13.08.2009

Используйте eval следующим образом:

var func = eval('(' + funcStr + ')');
person Andreas Grech    schedule 13.08.2009
comment
Так я думал изначально, но я уверен, что это относится только к объектам. - person karim79; 13.08.2009
comment
Кроме того, правильно это или неправильно..., это не работает в IE. - person ; 13.08.2009
comment
Пробовал это в IE и не работал eval ('(function(){return 'Yay'})')(). Однако eval ('[function(){return 'Yay'}][0]')() сработало - person Juan Mendes; 05.01.2011

Мы решили эту проблему, подготовив универсальный анализатор функций, который преобразует строку в настоящую функцию JavaScript:

if (typeof String.prototype.parseFunction != 'function') {
    String.prototype.parseFunction = function () {
        var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
        var match = funcReg.exec(this.replace(/\n/g, ' '));

        if(match) {
            return new Function(match[1].split(','), match[2]);
        }

        return null;
    };
}

примеры использования:

var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));

func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();

здесь находится jsfiddle

person Mr. Pumpkin    schedule 13.11.2014

Это тоже нормально.

var func = eval("_="+funcStr);
person gogog    schedule 26.01.2019

Что также работает

var myFunc = function(myParam){
   // function body here
}
person Zoidberg    schedule 13.08.2009

EVAL без eval()...

function evalEx(code){
  var result,D=document,S=D.createElement('script'),
  H=D.head||D.getElementsByTagName['head'][0],
  param=Array.prototype.slice.call(arguments);
  code='function evalWE(){'+code+'}';
  S.innerText===''?S.innerText=code:S.textContent=code;
  H.appendChild(S);
  result=evalWE.apply(this,param);
  H.removeChild(S);
  return result
}

Пример использования:

ABC=evalEx('return "ABC"');
nine=evalEx('return arguments[1]+arguments[2]',4,5);
person Ferdinand Liu    schedule 01.03.2012
comment
ха-ха, вы только что объяснили мне причину, по которой пакетные приложения Google запрещают встроенный javascript в HTML: developer.chrome .com/extensions/contentSecurityPolicy.html - person nraynaud; 02.12.2013

Простой пример определения функции в виде строки, eval()ing ее и передачи параметра при немедленном вызове функции (и последующем выводе результата на консоль):

console.log('eval: %s', eval("(function(foo) { return foo.bar; })")({"bar": "12345"}));

Это приводит к выводу, подобному следующему.

eval: 12345

person awhie29urh2    schedule 02.07.2013

function-serialization-tools предоставляет функцию s2f(), которая принимает строковое представление функцию и возвращает ее как функцию.

person lammy    schedule 29.12.2015