Wykonaj kod JavaScript przechowywany jako ciąg


173

Jak wykonać skrypt JavaScript będący ciągiem znaków?

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

Odpowiedzi:



134

Możesz to wykonać za pomocą funkcji. Przykład:

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

var F=new Function (theInstructions);

return(F());

3
ale w końcu - czy to nie to samo, co dzwonienie var F=function(){eval(theInstructions);};?
Jörn Berkefeld

14
tak i nie: z kodem eval byłby również wykonywany, podczas gdy z kodem Function () nie jest wykonywany do F () (przypadek użycia? sprawdź, czy nie ma błędu składni, ale nie chcesz wykonywać kodu)
G3z

2
@stefan It's beatifull ...new Function("alert('Hello World');")()
Andrés Morales

Wypróbowałem to w bloku try / catch i działa idealnie. Mogę teraz pobrać dowolny kod JavaScript wpisany do bloku tekstowego, przekazać go do mojej funkcji i wykonać. Blok catch może następnie wstawiać komunikaty o błędach z silnika JavaScript do elementu DOM i wyświetlać wszelkie błędy w kodzie. Jeśli ktoś chce funkcji, którą napisałem, to jak już ją posprzątam, mogę ją tutaj zamieścić.
David Edwards

@DavidEdwards Byłoby wspaniale, gdybyś nadal to miał i opublikował.
Anoop

60

evalFunkcja oceni ciąg znaków, który jest przekazywany do niego.

Ale używanie evalmoże być niebezpieczne , więc używaj go ostrożnie.

Edycja: annakata ma dobry punkt - jest nie tylko eval niebezpieczna , ale także powolna . Dzieje się tak, ponieważ kod, który ma zostać oceniony, musi zostać przeanalizowany na miejscu, więc zajmie to trochę zasobów obliczeniowych.


34
super niebezpieczne i wolne - powinieneś pogrubić, pochylić się, podkreślić i h1 to
annakata

5
Wątpię, czy jest to wolniejsze niż ładowanie JavaScript w dowolnym miejscu na stronie, to również musi zostać przeanalizowane. Jeśli jest wolniejszy, to dlatego, że jest wykonywany w innym zakresie, co może wymusić utworzenie zasobów dla tego zakresu.
cgp

6
Jeśli mówisz, że eval()to niebezpieczne. Czy jest jakaś alternatywa?
white_gecko

4
@coobird Wiem, że jest trochę późno, ale dlaczego jest to niebezpieczne? Użytkownik może łatwo uruchomić kod JavaScript w Twojej witrynie za pomocą konsoli.
jkd

7
jeśli twoje bezpieczeństwo w ogóle zależy od javascript po stronie klienta, spieprzyłeś dużo czasu i nie ma to nic wspólnego z eval.
Matthew

20

Użyj eval ().

Wycieczka po Eval Schools W3 . Witryna zawiera kilka użytecznych przykładów eval. Dokumentacja Mozilli opisuje to szczegółowo.

Prawdopodobnie otrzymasz wiele ostrzeżeń dotyczących bezpiecznego korzystania z tego. NIE zezwalaj użytkownikom na wstrzykiwanie czegokolwiek do eval (), ponieważ jest to ogromny problem bezpieczeństwa.

Będziesz także chciał wiedzieć, że eval () ma inny zakres .


11
w3fools.com . W3C nie ma nawet nic do powiedzenia na temat eval. Jeśli chcesz zamieścić
Bergi,

7
Nie chciałem umieszczać linków do niczego oficjalnego, chciałem linkować do czegoś czytelnego - patrząc na to , co podałeś , nie wyjaśnia, w jaki sposób jest używany, nie ma przykładów, nie ma sposobu, aby majstrować, i opisuje metodę oddzielnie . Dla początkującego jest to całkowicie nieodpowiedni link. Hej, nie byłbyś @bjorninge, prawda?
cgp

1
Specyfikacja opisuje evallepiej dla mnie niż ten artykuł W3Schools. Coś czytelnego, z dobrym wyjaśnieniem i przykładami, to developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . I nie, nie jestem bjorninge
Bergi

Zgodzę się, że to nie jest dokumentacja, i zgodzę się, że strona Mozilli jest lepszym ogólnym obrazem. Nieznacznie poprawiłem moją odpowiedź na podstawie opinii
cgp

1
Odnośnie tego linku ecma-international.org, opisałbym go jako czytelny i zrozumiały dla każdego, kto ma ponad 15-minutowe doświadczenie z JS. To bardzo miłe.
i336_

16

Spróbuj tego:

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

Osobiście tego nie testowałem, ale wydaje się, że działa.


1
Zapomniałeś o ucieczce przed zamknięciem> w skrypcie: var script = "<script type = \" text / javascript \ "> content </ script \>";
rlib

1
Dlaczego musisz uciec przed zamknięciem>?
Jools

11

Trochę tak, jak powiedział @Hossein Hadżizadeh Alerady, choć bardziej szczegółowo:

Istnieje alternatywa dla eval().

Funkcja setTimeout()została zaprojektowana do wykonania czegoś po upływie milisekund, a kod, który ma zostać wykonany, jest sformatowany jako łańcuch.

To działałoby tak:

ExecuteJavascriptString(); //Just for running it

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

1 oznacza, że ​​będzie czekał 1 milisekundę przed wykonaniem ciągu.

Może nie jest to najbardziej poprawny sposób, ale działa.


Po co marnować jedną milisekundę, skoro można przejść od 0 (zera) do setTimeout? Zauważ, że w każdym przypadku sprawi, że wykonanie będzie asynchroniczne. Oznacza to, że cały kod następujący po setTimeoutwywołaniu zostanie wywołany przed kodem przekazanym do setTimeout(nawet jeśli zostanie wywołany z wartością 0 (zero)).
jox

🤷‍♀️ po prostu pomyślałem, że lepiej wyjaśnia, jak działa setTimeout
Anton Juul-Naber

8
new Function('alert("Hello")')();

Myślę, że to najlepszy sposób.


7

Użyj eval jak poniżej. Eval należy używać z ostrożnością, proste wyszukiwanie hasła „ eval is evil ” powinno dać kilka wskazówek.

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    eval(s);
}

2
Dobra wskazówka, wystarczy wyszukać hasło „eval is evil”. Dzięki!
Taptronic

5

Sprawdziłem to w wielu skomplikowanych i zaciemnionych skryptach:

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);

5

Jeśli chcesz wykonać określone polecenie (czyli ciąg znaków) po określonym czasie - cmd = twój kod - InterVal = opóźnienie uruchomienia

 function ExecStr(cmd, InterVal) {
    try {
        setTimeout(function () {
            var F = new Function(cmd);
            return (F());
        }, InterVal);
    } catch (e) { }
}
//sample
ExecStr("alert(20)",500);

@SteelBrain dodaj próbkę uruchamianą przez ExecStr ("alert (20)", 500);
Hossein Hajizadeh

1
Dlaczego Valw InterValkapitalizowane?
Programy Redwolf

4

Dla użytkowników, którzy używają węzła i są zaniepokojeni konsekwencjami kontekstowymi eval()ofert nodejsvm . Tworzy maszynę wirtualną V8, która może sandboxować wykonywanie kodu w oddzielnym kontekście.

Pójście o krok dalej powoduje vm2utrudnienie, vmpozwalając maszynie wirtualnej na uruchomienie niezaufanego kodu.

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
Zamiast mówić „eval jest zło” i nie podawać kontekstu ani rozwiązania, w rzeczywistości próbuje to rozwiązać problem. +1 dla Ciebie
Redwolf Programs

3
eval(s);

Ale może to być niebezpieczne, jeśli pobierasz dane od użytkowników, chociaż przypuszczam, że jeśli wyrządzą im awarię własnej przeglądarki, to ich problem.


1
dokładnie. Eval jest niebezpieczny po stronie serwera. Na kliencie ... nie tak bardzo. Użytkownik może po prostu wpisać javascript: someevilcode do adresu przeglądarki i boomu. Eval właśnie tam.
Esben Skov Pedersen

@EsbenSkovPedersen Jest to zabronione przynajmniej w chrome i wymaga działania użytkownika, w przeciwieństwie do witryny, która koduje evalużytkowników, która może na przykład pozwolić użytkownikom na kradzież kont innych użytkowników bez ich wiedzy, po prostu ładując stronę.
1j01

1
@ 1j01 Szczerze mówiąc, mój komentarz ma pięć lat.
Esben Skov Pedersen

@EsbenSkovPedersen To prawda :)
1j01

2

Nie jestem pewien, czy to oszustwo, czy nie:

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

Odpowiadałem na podobne pytanie i wpadłem na kolejny pomysł, jak to osiągnąć bez użycia eval():

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

W powyższym kodzie zasadniczo tworzysz Blob, zawierający twój skrypt, w celu utworzenia adresu URL obiektu (reprezentacja obiektu File lub Blob w pamięci przeglądarki). Ponieważ masz srcwłaściwość na <script>tagu, skrypt zostanie wykonany w taki sam sposób, jakby został załadowany z dowolnego innego adresu URL.


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);

Pamiętaj jednak, że eval jest bardzo potężny i dość niebezpieczny. Lepiej mieć pewność, że wykonywany skrypt jest bezpieczny i niezmienny przez użytkowników.


1
W JS wszystko może zostać zmienione przez użytkownika, wystarczy wpisać "javascript: document.write (" Hello World ");" do paska adresu prawie każdej przeglądarki.
UnkwnTech

1
Tak, ale możesz mu to utrudnić, nie używając zmiennych globalnych, ukrywając swoje funkcje w domknięciach itp. Ponadto, unikając eval like the plague =)
PatrikAkerstrand

0

Można użyć matematyki

Fragment z powyższego linku:

// 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                                

scopeto jakikolwiek przedmiot. Więc jeśli przekażesz zasięg globalny do funkcji evalute, możesz być w stanie wykonać alert () dynamicznie.

Również mathjs jest znacznie lepszą opcją niż eval (), ponieważ działa w piaskownicy.

Użytkownik może próbować wstrzyknąć złośliwy kod JavaScript za pośrednictwem parsera wyrażeń. Parser wyrażeń mathjs oferuje środowisko piaskownicy do wykonywania wyrażeń, które powinny to uniemożliwiać. Możliwe jest jednak, że istnieją nieznane luki w zabezpieczeniach, dlatego należy zachować ostrożność, szczególnie podczas zezwalania na wykonywanie po stronie serwera dowolnych wyrażeń.

Nowsze wersje mathjs nie używają funkcji eval () ani Function ().

Parser aktywnie zapobiega dostępowi do wewnętrznej oceny skryptów JavaScripts i nowej funkcji, które są główną przyczyną ataków bezpieczeństwa. Mathjs w wersjach 4 i nowszych nie używa eval JavaScript pod maską. Wersja 3 i starsze używały eval na etapie kompilacji. Nie jest to bezpośrednio kwestia bezpieczeństwa, ale skutkuje większą możliwą powierzchnią ataku.


0

Używanie zarówno funkcji eval, jak i tworzenia nowej funkcji do wykonywania javascript wiąże się z wieloma zagrożeniami bezpieczeństwa.

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

Wolę tę metodę, aby wykonać JavaScript, który otrzymuję jako ciąg.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.