Executar código JavaScript armazenado como uma sequência

173

Como executo algum JavaScript que é uma string?

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    // how do I get a browser to alert('hello')?
}
divinci
fonte

Respostas:

227

Com eval("my script here")função.

Lennart Koopmann
fonte
11
Cuidado ! Isso vai executar o código, portanto, tenha cuidado de onde / como você conseguiu essa string. Lembre-se de que alguém pode tentar inserir código malicioso dentro da sua string.
8138 Jon
@divinci Isso é chamado de "Cross Site Scripting". Veja aqui: en.wikipedia.org/wiki/Cross-site_scripting .
Brendon Shaw
134

Você pode executá-lo usando uma função. Exemplo:

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

var F=new Function (theInstructions);

return(F());
Stefan
fonte
3
mas no final - não é o mesmo que ligar var F=function(){eval(theInstructions);};?
Jörn Berkefeld
14
sim e não: com código eval também seria executado, enquanto com código Function () não é executado até F () (caso de uso? verifique se há erro de sintaxe, mas não deseja executar o código)
G3z
2
@stefan It's beatifull ...new Function("alert('Hello World');")()
Andrés Morales
Eu tentei isso dentro de um bloco try / catch, e funciona perfeitamente. Agora posso pegar qualquer código JavaScript digitado em um bloco de texto, passá-lo para minha função e executá-lo. O bloco catch pode inserir mensagens de erro do mecanismo JavaScript em um elemento DOM e exibir quaisquer erros no código. Se alguém quiser a função que escrevi, depois de a arrumar, posso publicá-la aqui.
David Edwards
@DavidEdwards Seria incrível se você ainda o tem e o publica.
Anoop
60

A evalfunção avaliará uma string que é passada para ela.

Mas o uso de evalpode ser perigoso , portanto, use com cuidado.

Edit: annakata tem um bom argumento - não é apenas eval perigoso , é lento . Isso ocorre porque o código a ser avaliado deve ser analisado no local, de modo que serão necessários alguns recursos de computação.

coobird
fonte
34
Super perigoso e lento - você deve negrito, itálico, sublinhado, e h1 que
annakata
5
Duvido que seja mais lento do que carregar o JavaScript em qualquer outro lugar da página, que também tenha que ser analisado. Se for mais lento, é porque é feito em um escopo diferente, o que pode forçar a criação de recursos para esse escopo.
cgp
6
Se você diz que eval()é perigoso. Existe alguma alternativa?
22132 white_gecko
4
@coobird Eu sei que isso é um pouco tarde, mas por que isso é perigoso? O usuário pode executar facilmente o código JavaScript no seu site usando o console.
Jkd 23/03
8
se sua segurança depender de javascript do lado do cliente, você estragou tudo e não tem nada a ver com eval.
Matthew
20

Use eval ().

W3 Visita às escolas de avaliação . O site tem alguns exemplos úteis de avaliação. A documentação do Mozilla cobre isso em detalhes.

Você provavelmente receberá muitos avisos sobre como usá-lo com segurança. NÃO permita que os usuários injetem QUALQUER COISA no eval () , pois é um grande problema de segurança.

Você também vai querer saber que eval () tem um escopo diferente .

cgp
fonte
11
w3fools.com . O W3C nem tem nada a dizer sobre avaliação. Se você deseja criar um link para algo oficial, segmente ecma-international.org/ecma-262/5.1/#sec-15.1.2.1
Bergi
7
Eu não queria "vincular a nada oficial, queria vincular a algo legível - olhando para o que você vinculou, ele não explica como é usado, nem exemplos, nem como mexer, e descreve o método isoladamente. . para um iniciante, é um link completamente inadequada Ei, você não iria acontecer de ser @bjorninge, você.?
CGP
1
A especificação descreve evalmelhor para mim do que o artigo do W3Schools. Algo legível com boas explicações e exemplos seria developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . E não, eu não sou bjorninge
Bergi
Concordo que não é documentação e concordo que a página do mozilla é uma imagem geral melhor dela. Ajustou levemente minha resposta com base no feedback #
13353
1
Com relação ao link ecma-international.org, eu o descreveria como legível e apreciável por todos com mais de 15 minutos de experiência com JS. É muito bom.
I336_
16

Tente o seguinte:

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

Pessoalmente, não testei, mas parece funcionar.

yanko
fonte
1
Você esqueceu de fechar o fechamento> no script: var script = "<tipo de script = \" text / javascript \ "> conteúdo </ script \>";
Rlib
1
Por que você precisa escapar do fechamento>?
Jools
11

Um pouco como o que Hossein Hajizadeh alerady disse, embora com mais detalhes:

Existe uma alternativa para eval().

A função setTimeout() foi projetada para executar algo após um intervalo de milissegundos e o código a ser executado é formatado como uma sequência.

Funcionaria assim:

ExecuteJavascriptString(); //Just for running it

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

1 significa que ele aguardará 1 milissegundo antes de executar a sequência.

Pode não ser a maneira mais correta de fazê-lo, mas funciona.

Anton Juul-Naber
fonte
Por que desperdiçar um milissegundo quando você pode passar de 0 (zero) a setTimeout? Observe que, em qualquer caso, isso tornará a execução assíncrona. Isso significa que todo o código que segue a setTimeoutchamada será invocado antes da passagem do código setTimeout(mesmo se chamado com 0 (zero)).
jox 16/05
️ apenas pensei que era melhor explicar como o setTimeout funciona
Anton Juul-Naber
8
new Function('alert("Hello")')();

Eu acho que esse é o melhor caminho.

MyMeMo
fonte
7

Use eval como abaixo. Eval deve ser usado com cautela, uma simples pesquisa sobre " eval is evil " deve apontar algumas dicas.

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    eval(s);
}
xk0der
fonte
2
Boa dica sobre isso, uma simples pesquisa sobre "eval is evil" Obrigado!
Taptronic 02/06/2009
5

Verifiquei isso em muitos scripts complexos e ofuscados:

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
fonte
5

Se você deseja executar um comando específico (ou seja, string) após um tempo específico - cmd = seu código - InterVal = atraso na execução

 function ExecStr(cmd, InterVal) {
    try {
        setTimeout(function () {
            var F = new Function(cmd);
            return (F());
        }, InterVal);
    } catch (e) { }
}
//sample
ExecStr("alert(20)",500);
Hossein Hajizadeh
fonte
@SteelBrain adiciona uma amostra executada por ExecStr ("alert (20)", 500);
Hossein Hajizadeh
1
Por que está Valem InterValmaiúscula?
Programas Redwolf
4

Para usuários que estão usando o nó e que estão preocupados com as implicações de contexto das eval()ofertas do nodejs vm. Ele cria uma máquina virtual V8 que pode proteger a execução do seu código em um contexto separado.

Levar as coisas um passo adiante é o vm2que fortalece, vmpermitindo que a VM execute código não confiável.

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.
Eric Kigathi
fonte
2
Em vez de dizer "avaliar é mau" e não dar contexto ou solução, isso realmente tenta resolver o problema. +1 para você
Programas Redwolf
3
eval(s);

Mas isso pode ser perigoso se você estiver obtendo dados de usuários, embora eu suponha que se eles travarem o próprio navegador, isso é problema deles.

UnkwnTech
fonte
1
exatamente. Eval é perigoso no lado do servidor. No cliente ... nem tanto. O usuário pode apenas digitar javascript: someevilcode no endereço do navegador e no boom. Eval ali mesmo.
Esben Skov Pedersen
@EsbenSkovPedersen Isso é evitado pelo menos no chrome, e requer ação do usuário, em oposição a um site que evalé código de usuários, que poderia, por exemplo, permitir que os usuários roubassem contas de outros usuários sem que eles soubessem apenas carregando a página.
1j01 27/05
1
@ 1j01 Para ser sincero, meu comentário tem cinco anos.
Esben Skov Pedersen
@EsbenSkovPedersen Isso é verdade :)
1j01
2

Não tenho certeza se isso é trapaça ou não:

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
Zachary Scott
fonte
2

Eu estava respondendo a uma pergunta semelhante e tive outra ideia de como fazer isso sem usar eval():

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

No código acima, você basicamente cria o Blob, contendo seu script, para criar a URL do objeto (representação do objeto File ou Blob na memória do navegador). Como você possui srcpropriedade na <script>tag, o script será executado da mesma maneira como se tivesse sido carregado de qualquer outro URL.

akrn
fonte
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!');");
Oleg
fonte
0
eval(s);

Lembre-se, porém, que a avaliação é muito poderosa e insegura. É melhor você ter certeza de que o script que você está executando é seguro e imutável pelos usuários.

PatrikAkerstrand
fonte
1
No JS, tudo pode ser alterado pelo usuário, basta digitar "javascript: document.write (" Hello World ");" na barra de endereço de quase qualquer navegador.
Unkwntech
1
Sim, mas você pode torná-lo mais difícil para ele por não usar variáveis globais, escondendo suas funções no fechamento etc. Além disso, evitando eval como a peste =)
PatrikAkerstrand
0

Pode-se usar mathjs

Snippet do link acima:

// 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é qualquer objeto. Portanto, se você passar o escopo global para a função evalute, poderá executar alert () dinamicamente.

Além disso, mathjs é uma opção muito melhor que eval () porque é executado em uma sandbox.

Um usuário pode tentar injetar código JavaScript malicioso por meio do analisador de expressões. O analisador de expressões do mathjs oferece um ambiente em área restrita para executar expressões que devem tornar isso impossível. É possível, no entanto, que haja vulnerabilidades de segurança desconhecidas, por isso é importante ter cuidado, principalmente ao permitir a execução de expressões arbitrárias no servidor.

As versões mais recentes do mathjs não usam eval () ou Function ().

O analisador impede ativamente o acesso à avaliação interna do JavaScripts e à nova Function, que são a principal causa de ataques de segurança. As versões 4 e mais recentes do Mathjs não usam a avaliação do JavaScript por baixo. A versão 3 e anterior usava eval para a etapa de compilação. Isso não é diretamente um problema de segurança, mas resulta em uma maior superfície de ataque possível.

sziraqui
fonte
0

Usar o eval e criar uma nova função para executar o javascript traz muitos riscos à segurança.

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

Eu prefiro esse método para executar o Javascript que recebo como uma string.

MapMyMind
fonte