Выполнить код JavaScript, хранящийся в виде строки

173

Как мне выполнить JavaScript, который является строкой?

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    // how do I get a browser to alert('hello')?
}
divinci
источник

Ответы:

227

С eval("my script here")функцией.

Леннарт Купманн
источник
12
Будь осторожен ! Это выполнит код, поэтому будьте осторожны с тем, где / как вы получили эту строку. Помните, что любой может попытаться вставить вредоносный код в вашу строку.
Джон
1
@divinci Это называется «межсайтовый скриптинг». Смотрите здесь: en.wikipedia.org/wiki/Cross-site_scripting .
Брендон Шоу
133

Вы можете выполнить это с помощью функции. Пример:

var theInstructions = "alert('Hello World'); var x = 100";

var F=new Function (theInstructions);

return(F());
Штефана
источник
3
но в конце концов - разве это не то же самое, что звонить var F=function(){eval(theInstructions);};?
Йорн Беркефельд
14
да и нет: с кодом eval также будет выполняться, в то время как с кодом функции () код не будет выполняться до тех пор, пока F () (прецедент? проверять синтаксическую ошибку, но не хочет выполнять код)
G3z
2
@stefan Это красиво ...new Function("alert('Hello World');")()
Андрес Моралес
Я попробовал это внутри блока try / catch, и он отлично работает. Теперь я могу взять любой код JavaScript, введенный в текстовый блок, передать его в свою функцию и выполнить. Затем блок catch может вставлять сообщения об ошибках из механизма JavaScript в элемент DOM и отображать любые ошибки в коде. Если кому-то нужна функция, которую я написал, тогда, когда я приведу ее в порядок, я могу опубликовать ее здесь.
Дэвид Эдвардс
@DavidEdwards Было бы здорово, если у вас еще есть и опубликовать его.
Anoop
60

evalФункция будет оценивать строку , которая передается ему.

Но использование evalможет быть опасным , поэтому используйте с осторожностью.

Редактировать: Аннаката имеет хорошее замечание - это не только eval опасно , но и медленно . Это связано с тем, что анализируемый код должен быть проанализирован на месте, что потребует некоторых вычислительных ресурсов.

coobird
источник
34
супер опасный и медленный - вы должны
выделять
5
Я сомневаюсь, что это медленнее, чем загрузка JavaScript где-либо еще на странице, который также должен быть проанализирован. Если это медленнее, это потому, что это делается в другой области, что может привести к созданию ресурсов для этой области.
CGP
6
Если вы говорите, eval()это опасно. Есть ли альтернатива?
white_gecko
4
@coobird Я знаю, что немного поздно, но почему это опасно? Пользователь может легко запустить код JavaScript на вашем сайте, используя консоль.
JKD
8
если ваша безопасность вообще зависит от клиентского javascript, вы облажались, и это не имеет ничего общего с eval.
Матфея
20

Используйте eval ().

W3 Школьный тур по eval . На сайте есть несколько полезных примеров eval. Документация Mozilla подробно описывает это.

Вы вероятно получите много предупреждений об использовании этого безопасно. НЕ позволяйте пользователям вводить НИЧЕГО в eval (), так как это огромная проблема безопасности.

Вы также хотите знать, что eval () имеет другую область видимости .

CGP
источник
11
4PDA . W3C даже не имеет ничего сказать о Eval. Если вы хотите , чтобы ссылка на что - то чиновник, целевой ecma-international.org/ecma-262/5.1/#sec-15.1.2.1
Берги
7
Я не хотел «ссылаться на что-то официальное, я хотел ссылаться на что-то читаемое - Глядя на то, что вы связали, он не дает объяснения того, как он используется, нет примеров, нет способа повозиться и описывает метод отдельно». Для новичка это совершенно неуместная ссылка. Эй, вы бы не оказались @bjorninge, не так ли?
cgp
1
Спецификация описывает evalдля меня лучше, чем та статья W3Schools. Что-то читаемое с хорошим объяснением и примерами будет developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . И нет, я не бьорнинге
Берги
Я согласен с тем, что это не документация, и я согласен с тем, что страница Mozilla представляет собой более полную картину. Немного подправил мой ответ, основываясь на отзывах
cgp
1
Что касается этой ссылки на ecma-international.org, я бы назвал ее читабельной и заметной для всех, кто имеет опыт работы с JS более 15 минут. Это очень приятно.
i336_
16

Попробуй это:

  var script = "<script type='text/javascript'> content </script>";
  //using jquery next
  $('body').append(script);//incorporates and executes inmediatelly

Лично я не проверял это, но, кажется, работает.

Янко
источник
1
Вы забыли избежать закрытия> в скрипте: var script = "<script type = \" text / javascript \ "> content </ script \>";
Rlib
1
Зачем вам нужно избегать закрытия>?
Jools
11

Немного похоже на то, что сказал @Hossein Hajizadeh alerady, хотя более подробно:

Есть альтернатива eval().

Функция setTimeout()предназначена для выполнения чего-либо после интервала в миллисекунды, и код, который должен быть выполнен, просто отформатирован в виде строки.

Это будет работать так:

ExecuteJavascriptString(); //Just for running it

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    setTimeout(s, 1);
}

1 означает, что он будет ждать 1 миллисекунду перед выполнением строки.

Возможно, это не самый правильный способ сделать это, но это работает.

Антон Юул-Набер
источник
Зачем тратить одну миллисекунду, если вы можете передать 0 (ноль) setTimeout? Обратите внимание, что в любом случае это сделает выполнение асинхронным. Это означает, что весь код, который следует за setTimeoutвызовом, будет вызван до того, как код будет передан setTimeout(даже если вызван с 0 (ноль)).
Jox
Thought просто подумал, что лучше объяснить, как работает setTimeout
Антон Джуль-Набер
8
new Function('alert("Hello")')();

Я думаю, что это лучший способ.

MyMeMo
источник
7

Используйте eval, как показано ниже. Eval следует использовать с осторожностью, простой поиск « eval is evil » должен привести к появлению некоторых указателей.

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    eval(s);
}
xk0der
источник
2
Хороший совет о том, что простой поиск "eval is evil" Спасибо!
Taptronic
5

Проверено это на многих сложных и запутанных скриптах:

var js = "alert('Hello, World!');" // put your JS code here
var oScript = document.createElement("script");
var oScriptText = document.createTextNode(js);
oScript.appendChild(oScriptText);
document.body.appendChild(oScript);
rlib
источник
5

Если вы хотите выполнить определенную команду (то есть строку) через определенное время - cmd = ваш код - InterVal = задержка для запуска

 function ExecStr(cmd, InterVal) {
    try {
        setTimeout(function () {
            var F = new Function(cmd);
            return (F());
        }, InterVal);
    } catch (e) { }
}
//sample
ExecStr("alert(20)",500);
Хоссейн Гаджизаде
источник
@SteelBrain добавить пример запуска ExecStr ("alert (20)", 500);
Хоссейн Гаджизаде
1
Почему Valв InterValзаглавной?
Программы
4

Для пользователей, которые используют узел и которые связаны с контекстными последствиями eval()предложений nodejs vm. Он создает виртуальную машину V8, которая может изолировать выполнение вашего кода в отдельном контексте.

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

const vm = require('vm');

const x = 1;

const sandbox = { x: 2 };
vm.createContext(sandbox); // Contextify the sandbox.

const code = 'x += 40; var y = 17;';
// `x` and `y` are global variables in the sandboxed environment.
// Initially, x has the value 2 because that is the value of sandbox.x.
vm.runInContext(code, sandbox);

console.log(sandbox.x); // 42
console.log(sandbox.y); // 17

console.log(x); // 1; y is not defined.
Эрик Кигати
источник
2
Вместо того, чтобы говорить «eval is evil» и не давать контекста или решения, это фактически пытается решить проблему. +1 для вас
программы
3
eval(s);

Но это может быть опасно, если вы принимаете данные от пользователей, хотя я полагаю, что если они сломают собственный браузер, это их проблема.

UnkwnTech
источник
1
именно. Eval опасен на стороне сервера. На клиенте ... не так уж и много. Пользователь может просто набрать в javascript: someevilcode в адрес браузера и бум. Эвал прямо там.
Эсбен Сков Педерсен
@EsbenSkovPedersen По крайней мере, это запрещено в chrome, и требует действий пользователя, в отличие от сайта evalс кодом от пользователей, который может, например, позволить пользователям красть учетные записи других пользователей без их ведома, просто загружая страницу.
1j01
1
@ 1j01 Честно говоря, моему комментарию пять лет.
Эсбен Сков Педерсен
@EsbenSkovPedersen Это правда :)
1j01
2

Не уверен, что это обман или нет:

window.say = function(a) { alert(a); };

var a = "say('hello')";

var p = /^([^(]*)\('([^']*)'\).*$/;                 // ["say('hello')","say","hello"]

var fn = window[p.exec(a)[1]];                      // get function reference by name

if( typeof(fn) === "function") 
    fn.apply(null, [p.exec(a)[2]]);                 // call it with params
Захари Скотт
источник
2

Я отвечал на аналогичный вопрос и получил еще одну идею, как этого добиться без использования eval():

const source = "alert('test')";
const el = document.createElement("script");
el.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
document.head.appendChild(el);

В приведенном выше коде вы в основном создаете Blob, содержащий ваш скрипт, чтобы создать URL объекта (представление объекта File или Blob в памяти браузера). Поскольку у вас есть srcсвойство для <script>тега, скрипт будет выполняться так же, как если бы он был загружен с любого другого URL.

AKRN
источник
2
function executeScript(source) {
    var script = document.createElement("script");
    script.onload = script.onerror = function(){ this.remove(); };
    script.src = "data:text/plain;base64," + btoa(source);
    document.body.appendChild(script);
}

executeScript("alert('Hello, World!');");
Олег
источник
0
eval(s);

Помните, однако, что Eval очень мощный и довольно небезопасный. Лучше быть уверенным в том, что выполняемый скрипт является безопасным и неизменным для пользователей.

PatrikAkerstrand
источник
1
В JS все может быть изменено пользователем, просто наберите "javascript: document.write (" Hello World ");" почти в любой адресной строке браузера.
UnkwnTech
1
Да, но вы можете усложнить ему задачу, не используя глобальные переменные, скрывая свои функции в замыканиях и т. Д. Также избегая eval, как чума =)
PatrikAkerstrand
0

Можно использовать mathjs

Фрагмент сверху ссылки:

// evaluate expressions
math.evaluate('sqrt(3^2 + 4^2)')        // 5
math.evaluate('sqrt(-4)')               // 2i
math.evaluate('2 inch to cm')           // 5.08 cm
math.evaluate('cos(45 deg)')            // 0.7071067811865476

// provide a scope
let scope = {
    a: 3,
    b: 4
}
math.evaluate('a * b', scope)           // 12
math.evaluate('c = 2.3 + 4.5', scope)   // 6.8
scope.c                                

scopeэто любой объект. Поэтому, если вы передадите глобальную область в функцию evalute, вы сможете динамически выполнять alert ().

Также mathjs - намного лучший вариант, чем eval (), потому что он работает в песочнице.

Пользователь может попытаться внедрить вредоносный код JavaScript через анализатор выражений. Парсер выражений mathjs предлагает изолированную среду для выполнения выражений, которая должна сделать это невозможным. Однако возможно, что существуют неизвестные уязвимости безопасности, поэтому важно соблюдать осторожность, особенно когда разрешается выполнение произвольных выражений на стороне сервера.

Более новые версии mathjs не используют eval () или Function ().

Парсер активно предотвращает доступ к внутреннему eval и новым функциям JavaScripts, которые являются основной причиной атак безопасности. Mathjs версии 4 и новее не использует eval-код JavaScript под капотом. Версия 3 и старше использовали eval для этапа компиляции. Это не является прямой проблемой безопасности, но приводит к большей возможной атаке.

sziraqui
источник
0

Использование eval и создание новой функции для выполнения javascript сопряжено с множеством угроз безопасности.

const script = document.createElement("script");
const stringJquery = '$("#button").on("click", function() {console.log("hit")})';
script.text = stringJquery;
document.body.appendChild(script);

Я предпочитаю этот метод для выполнения Javascript, который я получаю в виде строки.

MapMyMind
источник