Чи є спосіб створити функцію з рядка з javascript?


107

Наприклад;

var s = "function test(){
  alert(1);
}";

var fnc = aMethod(s);

Якщо це рядок, я хочу функцію, яка називається fnc. І fnc();вискакує екран попередження.

eval("alert(1);") не вирішує мою проблему.

Відповіді:


73

Я додав тест jsperf для 4-х різних способів створення функції з рядка:

  • Використання RegExp з класом функцій

    var func = "function (a, b) { return a + b; }".parseFunction();

  • Використання класу функцій із "return"

    var func = new Function("return " + "function (a, b) { return a + b; }")();

  • Використання офіційного конструктора функцій

    var func = new Function("a", "b", "return a + b;");

  • Використання Eval

    eval("var func = function (a, b) { return a + b; };");

http://jsben.ch/D2xTG

2 результати вибірки: введіть тут опис зображення введіть тут опис зображення


@KthProg Охолоджується;). Це не завжди погано, як у цій ситуації, jsperf в даний момент знижений, на щастя, я додав результати скріншотів до того, як він був знижений, коли я отримав коментар від Масового.
phnah

@KthProg FYI це була відповідна консервація, породжена системою модерації :), вона з'являється в черзі, і ми перевіряємо наперед визначені проблеми, однією з яких цей коментар призначений для виправлення. Це не важке і швидке правило, і ви помітите, що коментар у формі пропозиції, а не команди.
Ден Сміт

174

Кращим способом створення функції з рядка є використання Function:

var fn = Function("alert('hello there')");
fn();

Це має як перевагу / недолік, що змінні в поточній області (якщо не глобальні) не застосовуються до щойно побудованої функції.

Передача аргументів також можлива:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'

5
Погодьтеся, Functionви не забруднюєте локальну сферу, і саме тому evalоптимізація настільки важка для двигунів ... На прикладі ОП я б:var fnc = Function('return '+s)();
CMS

Я думаю, що це, мабуть, має бути прийнятою відповіддю. Це набагато безпечніше, ніж eval ().
Брайан Рейнер

Ти, друже мій, заслуговуєш на багато нагород. Це має перевагу у створенні об’єкта функції, який можна призначити подіям тощо. Наприклад: element.onclick = Функція ("сигнал ('тест"); ");
Райан Гріггс

1
@RyanGriggs У вашому випадку вам не потрібна функція "eval", тому краще писати як element.onclick = function() { alert("test"); }.
Лекенштейн

1
Ви маєте рацію з мого прикладу. Однак якщо ви хочете призначити довільні функції, що зберігаються в рядках, ваш метод ідеальний. Це те, що я насправді намагаюся зробити. У мене є кілька функцій, які зберігаються в рядкових змінних, і хочу призначити одну з дією onclick.
Ryan Griggs

38

Ви досить близькі.

//Create string representation of function
var s = "function test(){  alert(1); }";

//"Register" the function
eval(s);

//Call the function
test();

Ось робоча загадка .


Я знав, що функція оголошена, але не міг здогадатися називати ім'я функції. Дуже дякую.
ymutlu

4
Обов’язкове evalпопередження для майбутніх пошукових запитів: evalможна відкрити лазівки для хакерів: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, але якщо ви знаєте його небезпеку і можете їх уникнути, то це хороший простий спосіб створити функцію з рядка

що робити, якщо у вас немає назви функції, оскільки вона прийшла із запису бази даних?
Марсель Джаман

13

Так, використання Function- це чудове рішення, але ми можемо піти трохи далі і підготувати універсальний аналізатор, який розбирає рядок і перетворює його в реальну функцію 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


привіт, будь ласка, підтримка стрілки функції підтримки цього методу?
сатиш кумар

1
Я отримую цю помилку в typecirpt "Властивість" parseFunction "не існує для типу" String "."
Сегоне

11

Імена динамічних функцій у JavaScript

Використання Function

var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'

Джерело: http://marcosc.com/2012/03/dynamic-function-names-in-javascript/

Використання eval

var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'

Використання sjsClass

https://github.com/reduardo7/sjsClass

Приклад

Class.extend('newClassName', {
    __constructor: function() {
        // ...
    }
});

var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'

6

Цей прийом може бути в кінцевому рахунку еквівалентний методу eval, але я хотів його додати, оскільки він може бути корисним для деяких.

var newCode = document.createElement("script");

newCode.text = "function newFun( a, b ) { return a + b; }";

document.body.appendChild( newCode );

Це функціонально як додавання цього елемента <script> в кінець документа, наприклад:

...

<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>

</body>
</html>


1

Приклад з динамічними аргументами:

let args = {a:1, b:2}
  , fnString = 'return a + b;';

let fn = Function.apply(Function, Object.keys(args).concat(fnString));

let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))

Дякую. Дуже цікаво
Васильев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.