Thực thi mã JavaScript được lưu trữ dưới dạng chuỗi


173

Làm cách nào để thực thi một số JavaScript là một chuỗi?

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

Câu trả lời:



134

Bạn có thể thực hiện nó bằng cách sử dụng một chức năng. Thí dụ:

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

var F=new Function (theInstructions);

return(F());

3
nhưng cuối cùng - không giống như gọi điện thoại var F=function(){eval(theInstructions);};sao?
Jorn Berkefeld

14
có và không: với mã eval cũng sẽ được thực thi, trong khi với mã Hàm () không được thực thi cho đến khi F () (trường hợp sử dụng? kiểm tra lỗi cú pháp nhưng không muốn thực thi mã)
G3z

2
@stefan Thật tuyệt vời ...new Function("alert('Hello World');")()
Andrés Morales

Tôi đã thử điều này trong một khối thử / bắt và nó hoạt động hoàn hảo. Bây giờ tôi có thể lấy bất kỳ mã JavaScript nào được nhập vào một khối văn bản, chuyển nó vào hàm của tôi và thực thi nó. Sau đó, khối bắt có thể chèn thông báo lỗi từ công cụ JavaScript vào phần tử DOM và hiển thị bất kỳ lỗi nào trong mã. Nếu ai đó muốn chức năng tôi đã viết, thì một khi tôi đã dọn dẹp nó, tôi có thể đăng nó ở đây.
David Edwards

@DavidEdwards Sẽ thật tuyệt vời nếu bạn vẫn có nó và đăng nó.
Anoop

60

Các evalchức năng sẽ đánh giá một chuỗi được truyền cho nó.

Nhưng việc sử dụng evalcó thể nguy hiểm , vì vậy sử dụng một cách thận trọng.

Chỉnh sửa: annakata có một điểm tốt - Không chỉ eval nguy hiểm , nó còn chậm . Điều này là do mã được đánh giá phải được phân tích cú pháp tại chỗ, do đó sẽ mất một số tài nguyên tính toán.


34
siêu nguy hiểm VÀ chậm chạp - bạn nên in đậm, in nghiêng, gạch chân và h1 đó
annakata

5
Tôi nghi ngờ rằng nó chậm hơn so với việc tải JavaScript ở bất kỳ nơi nào khác trên trang, điều đó cũng phải được phân tích cú pháp. Nếu nó chậm hơn, thì đó là vì nó được thực hiện ở một phạm vi khác, điều này có thể buộc phải tạo ra các tài nguyên cho phạm vi đó.
cgp

6
Nếu bạn nói eval()là nguy hiểm. Có sự thay thế nào không?
trắng_gecko

4
@coobird Tôi biết điều này hơi muộn nhưng tại sao lại nguy hiểm? Người dùng có thể dễ dàng chạy mã JavaScript trên trang web của bạn bằng bảng điều khiển.
jkd

7
nếu bảo mật của bạn hoàn toàn phụ thuộc vào javascript phía máy khách, bạn đã làm hỏng thời gian lớn và nó không liên quan gì đến eval.
Matthew

20

Sử dụng eval ().

W3 Trường tham quan eval . Trang web có một số ví dụ có thể sử dụng của eval. Tài liệu Mozilla bao gồm chi tiết này.

Bạn có thể sẽ nhận được rất nhiều cảnh báo về việc sử dụng này một cách an toàn. KHÔNG cho phép người dùng tiêm BẤT CỨ vào eval () vì đây là một vấn đề bảo mật rất lớn.

Bạn cũng sẽ muốn biết rằng eval () có phạm vi khác .


11
w3fools.com . W3C thậm chí không có bất cứ điều gì để nói về eval. Nếu bạn muốn liên kết đến một cái gì đó chính thức, hãy nhắm mục tiêu ecma
i Intl.org/ecma-262/5.1/#sec-15.1.2.1

7
Tôi không muốn "liên kết với bất cứ điều gì chính thức, tôi muốn liên kết đến một cái gì đó có thể đọc được - Nhìn vào những gì bạn liên kết, nó không đưa ra lời giải thích nào về cách sử dụng nó, không có ví dụ, không có cách nào để khắc phục và mô tả phương pháp một cách cô lập Đối với người mới bắt đầu, đó là một liên kết hoàn toàn không phù hợp. Này, bạn sẽ không phải là @bjorninge, phải không?
cgp

1
Thông số kỹ thuật mô tả evaltốt hơn với tôi so với bài viết đó của W3Schools. Một cái gì đó có thể đọc được với lời giải thích tốt và ví dụ sẽ là developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ,. Và không, tôi không phải là bjorninge
Bergi

Tôi sẽ đồng ý rằng đó không phải là tài liệu và tôi sẽ đồng ý rằng trang của mozilla là một bức tranh tổng thể tốt hơn về nó. Hơi điều chỉnh câu trả lời của tôi dựa trên phản hồi
cgp

1
Về liên kết ecma-i Intl.org, tôi sẽ mô tả nó là dễ đọc và được mọi người đánh giá cao với hơn 15 phút trải nghiệm với JS. Nó rất đẹp
i336_

16

Thử cái này:

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

Cá nhân, tôi đã không kiểm tra nó nhưng dường như làm việc.


1
Bạn đã quên thoát đóng> trong tập lệnh: var script = "<script type = \" text / javascript \ "> nội dung </ script \>";
rlib

1
Tại sao bạn cần thoát khỏi việc đóng cửa>?
Jools

11

Một chút giống như những gì @Hossein Hajizadeh alerady đã nói, mặc dù chi tiết hơn:

Có một sự thay thế cho eval().

Hàm setTimeout()được thiết kế để thực thi một cái gì đó sau một khoảng thời gian tính bằng mili giây và mã được thực thi chỉ để được định dạng dưới dạng một chuỗi.

Nó sẽ hoạt động như thế này:

ExecuteJavascriptString(); //Just for running it

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

1 có nghĩa là nó sẽ đợi 1 mili giây trước khi thực hiện chuỗi.

Nó có thể không phải là cách chính xác nhất để làm điều đó, nhưng nó hoạt động.


Tại sao phải lãng phí một phần nghìn giây khi bạn có thể vượt qua 0 (không) setTimeout? Lưu ý rằng trong mọi trường hợp, nó sẽ làm cho việc thực thi không đồng bộ. Điều đó có nghĩa là tất cả các mã theo sau setTimeoutcuộc gọi sẽ được gọi trước khi mã được chuyển đến setTimeout(ngay cả khi được gọi bằng 0 (không)).
Jox

Chỉ cần nghĩ rằng nó giải thích rõ hơn về cách hoạt động của setTimeout
Anton Juul-Naber

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

Tôi nghĩ rằng đây là cách tốt nhất.


7

Sử dụng eval như dưới đây. Eval nên được sử dụng một cách thận trọng, một tìm kiếm đơn giản về " eval là ác " nên ném một số gợi ý.

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

2
Mẹo hay về việc tìm kiếm đơn giản về "eval is evil" Cảm ơn!
Taptronic

5

Đã kiểm tra điều này trên nhiều tập lệnh phức tạp và khó hiểu:

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

Nếu bạn muốn thực thi một lệnh cụ thể (đó là chuỗi) sau một thời gian cụ thể - cmd = mã của bạn - InterVal = delay để chạy

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

@SteelBrain thêm một mẫu được chạy bởi ExecStr ("alert (20)", 500);
Hossein Hajizadeh

1
Tại sao Valtrong InterValhoa?
Chương trình Redwolf

4

Đối với người dùng đang sử dụng nút và có liên quan đến ý nghĩa ngữ cảnh của các ưu eval()đãi của nodejsvm . Nó tạo ra một máy ảo V8 có thể tạo hộp cát cho việc thực thi mã của bạn trong một ngữ cảnh riêng.

Tiến xa hơn một bước là vm2làm cứng vmcho phép vm chạy mã không tin cậy.

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
Thay vì nói "eval là xấu xa" và không đưa ra bối cảnh hay giải pháp nào, điều này thực sự cố gắng giải quyết vấn đề. +1 cho bạn
Chương trình Redwolf

3
eval(s);

Nhưng điều này có thể nguy hiểm nếu bạn lấy dữ liệu từ người dùng, mặc dù tôi cho rằng nếu họ gặp sự cố trình duyệt của họ thì đó là vấn đề của họ.


1
chính xác. Eval là nguy hiểm về phía máy chủ. Trên máy khách ... không nhiều lắm. Người dùng chỉ cần nhập javascript: someevilcode vào địa chỉ của trình duyệt và bùng nổ. Eval ngay đó.
Esben Skov Pedersen

@EsbenSkovPedersen Điều đó ít nhất được ngăn chặn bằng chrome và nó yêu cầu hành động của người dùng, trái ngược với một trang web có evalmã từ người dùng, ví dụ, có thể cho phép người dùng đánh cắp tài khoản của người dùng khác mà họ không biết chỉ bằng cách tải trang.
1j01

1
@ 1j01 Để công bằng nhận xét của tôi là năm tuổi.
Esben Skov Pedersen

@EsbenSkovPedersen Điều đó đúng :)
1j01

2

Không chắc đây có phải là gian lận hay không:

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

Tôi đã trả lời câu hỏi tương tự và có một ý tưởng khác làm thế nào để đạt được điều này mà không cần sử dụng eval():

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

Trong đoạn mã trên, về cơ bản bạn tạo Blob, chứa tập lệnh của bạn, để tạo URL đối tượng (đại diện cho đối tượng Tệp hoặc Blob trong bộ nhớ trình duyệt). Vì bạn có thuộc srctính trên <script>thẻ, tập lệnh sẽ được thực thi theo cách tương tự như khi nó được tải từ bất kỳ URL nào khác.


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

Hãy nhớ rằng, eval đó rất mạnh mẽ và khá không an toàn. Bạn nên tự tin rằng tập lệnh bạn đang thực thi là an toàn và không thể thay đổi bởi người dùng.


1
Trong JS, mọi thứ có thể được thay đổi bởi người dùng chỉ cần gõ "javascript: document.write (" Hello World ");" vào hầu hết các thanh địa chỉ của trình duyệt.
UnkwnTech

1
Có, nhưng bạn có thể làm cho nó khó khăn hơn cho anh ta bằng cách không sử dụng các biến toàn cầu, ẩn chức năng của mình trong việc đóng cửa vv Ngoài ra, bằng cách tránh eval như bệnh dịch hạch =)
PatrikAkerstrand

0

Người ta có thể sử dụng mathjs

Đoạn trích từ liên kết trên:

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

scopelà bất kỳ đối tượng. Vì vậy, nếu bạn chuyển phạm vi toàn cầu cho hàm evalute, bạn có thể thực hiện cảnh báo () một cách linh hoạt.

Ngoài ra mathjs là lựa chọn tốt hơn nhiều so với eval () vì nó chạy trong hộp cát.

Một người dùng có thể thử tiêm mã JavaScript độc hại thông qua trình phân tích cú pháp biểu thức. Trình phân tích cú pháp biểu thức của mathjs cung cấp một môi trường hộp cát để thực thi các biểu thức sẽ làm cho điều này là không thể. Mặc dù có thể có các lỗ hổng bảo mật không xác định, do đó, điều quan trọng là phải cẩn thận, đặc biệt là khi cho phép phía máy chủ thực hiện các biểu thức tùy ý.

Các phiên bản mới hơn của mathjs không sử dụng eval () hoặc Function ().

Trình phân tích cú pháp chủ động ngăn chặn truy cập vào JavaScripts nội bộ và Hàm mới là nguyên nhân chính của các cuộc tấn công bảo mật. Mathjs phiên bản 4 và mới hơn không sử dụng eval của JavaScript dưới mui xe. Phiên bản 3 trở lên đã sử dụng eval cho bước biên dịch. Đây không phải là vấn đề bảo mật trực tiếp nhưng dẫn đến bề mặt tấn công lớn hơn có thể.


0

Sử dụng cả eval và tạo một Hàm mới để thực thi javascript đi kèm với rất nhiều rủi ro bảo mật.

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

Tôi thích phương thức này để thực thi Javascript tôi nhận được dưới dạng chuỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.