Создать несколько функций из одного источника JavaScript в виде строки - PullRequest
0 голосов
/ 11 мая 2019

Я хочу создать три функции из одной строки javascript, содержащей исходный код js.

Допустим, у меня есть следующий код в виде одной строки:

"
function func1()
{
    console.log('This comes from func1')
}

function func2()
{
    console.log('This comes from func2')
}

function func3()
{
    console.log('This comes from func3')
}
"

Теперь я хочу создать эти три функции как функции javascript и прикрепить их к объекту, например:

object1.func1 = function func1(){...}
object1.func2 = function func2(){...}

У меня много объектов и я хочу иметь возможность прикрепить файл скрипта, который содержит эти три функции func1, func2 и func3. Файл сценария может содержать и другие функции, но они вызываются одной из трех функций. Таким образом, файл сценария для объекта может выглядеть следующим образом:

"
// Main functions of a script file
// A script file MUST contain these three functions

function func1()
{
    console.log('This comes from func1')
    userFunc1();
    // do some user code
}

function func2()
{
    console.log('This comes from func2')
    userFunc2();
    // do some user code
}

function func3()
{
    console.log('This comes from func3')
    userFunc3();
    userFunc4();
    // do some user code
}


// User functions
// these are optional

function userFunc1()
{
    // do stuff
}

function userFunc2()
{
    // do stuff
}

function userFunc3()
{
    // do stuff
}

function userFunc4()
{
    // do stuff
}

"

У меня нет проблем с созданием функции, когда строка содержит только одну функцию, например:

var jsCode = "(function func1(){console.log('This comes from func1')})";
var script=new Function (jsCode);
script();

Моя проблема в том, как разобрать две или более функции из одной строки и создать эти функции соответственно?

Я не хочу использовать какие-либо библиотеки, только чистый JavaScript и я не хочу использовать eval, потому что он кажется ужасно медленным.

Может кто-нибудь помочь мне с этой проблемой?

1 Ответ

2 голосов
/ 11 мая 2019

При работе в браузере вы можете динамически добавить элемент script и выполнить его с помощью createContextualFragment :

function executeCode(code) {
    document.head.appendChild(
        document.createRange().createContextualFragment('<script>' + code + '<\/script>')
    );
}

// Demo
const code = `
function func1()
{
    console.log('This comes from func1')
}

function func2()
{
    console.log('This comes from func2')
}

function func3()
{
    console.log('This comes from func3')
}`;

executeCode(code);

func1();
func2();
func3();

Получение функций, загруженных как члены объекта

После обновления вопроса функции должны быть членами объекта. В этом случае я бы попросил, чтобы предоставленный код соответствовал этому формату:

({
    func1()
    {
        console.log('This comes from func1')
    },
    func2()
    {
        console.log('This comes from func2')
    },
    func3()
    {
        console.log('This comes from func3')
    }
})

Затем вы можете использовать eval, чтобы получить выражение этого объекта в переменную:

const code = `
    ({
        func1()
        {
            console.log('This comes from func1')
        },
        func2()
        {
            console.log('This comes from func2')
        },
        func3()
        {
            console.log('This comes from func3')
        }
    })
`;

const obj = eval(code);

obj.func1();
obj.func2();
obj.func3();

Менее навязчивым изменением формата кода было бы сделать его выражением массива:

const code = `
    [
        function func1()
        {
            console.log('This comes from func1')
        },
        function func2()
        {
            console.log('This comes from func2')
        },
        function func3()
        {
            console.log('This comes from func3')
        }
    ]
`;

const obj = Object.fromEntries(eval(code).map(f => [f.name, f]));

obj.func1();
obj.func2();
obj.func3();

Когда код нельзя изменить

Если ваш текущий синтаксис не может быть изменен, то я бы предложил заменить его на строку, чтобы получить вышеупомянутый синтаксис массива:

const code = `
function func1()
{
    console.log('This comes from func1')
}

function func2()
{
    console.log('This comes from func2')
}

function func3()
{
    console.log('This comes from func3')
}`;

const array = "[" + code.replace(/}(\s*function\b)/g, "},$1") + "]";

const obj = Object.fromEntries(eval(array).map(f => [f.name, f]));

obj.func1();
obj.func2();
obj.func3();

Очевидно, что такая замена строки имеет некоторые недостатки, так как код может иметь вложенные функции, и они должны , а не получать дополнительную запятую (хотя это не всегда нарушает код). Можно также представить код со строковыми литералами, которые имеют последовательность } function в них, ... и т. Д., ... и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...