Làm cách nào để gọi một hàm có chuỗi trong JavaScript?

Gọi một hàm từ một chuỗi, được lưu trữ trong một biến có thể được thực hiện theo hai cách khác nhau. Cách tiếp cận đầu tiên sử dụng phương thức đối tượng cửa sổ và phương thức thứ hai sử dụng hàm eval()

Hướng dẫn này sẽ hướng dẫn bạn tìm hiểu cách thực thi một hàm JavaScript bằng cách sử dụng tên của nó dưới dạng chuỗi

Sử dụng phương thức window[]()

Ở đây, để thực thi hàm sử dụng tên hàm dưới dạng chuỗi, chuỗi phải được thay đổi thành con trỏ bằng cú pháp sau

cú pháp

var functionName = "string";
functionName = window[functionName]( parameters );

Ở đây chúng tôi đã lưu trữ một chuỗi dưới dạng tên hàm và giá trị này được gọi bằng window[]

thuật toán

  • BƯỚC 1 – Xác định hàm để hiển thị đầu ra

  • BƯỚC 2 – Xác định một hàm khác và gán tên của hàm đầu ra dưới dạng một chuỗi trong một biến toàn cục. Nếu được yêu cầu, một tham số có thể được chuyển vào hàm đầu ra

  • BƯỚC 3 - Bây giờ hãy gọi biến toàn cục này bên trong window[], biến này sẽ thực thi hàm đầu ra

Thí dụ

Trong ví dụ dưới đây, showOutput là hàm được xác định để hiển thị đầu ra. winObjFunc được xác định để thực hiện hành động window[] đối với tên hàm showOutput được lưu trữ trong biến toàn cục strFunc. Sử dụng cú pháp trên, hàm showOutput được gọi và chúng ta thực hiện hàm

Using the window object method to execute function with its string name.

Sử dụng Phương thức eval()

Để thực thi hàm sử dụng tên hàm dưới dạng chuỗi, có thể sử dụng eval(). Trong trường hợp này, các đối số của hàm có thể là một câu lệnh, một biểu thức, các biến, thuộc tính của các đối tượng hiện có hoặc một chuỗi các biểu thức. Thực hiện theo cú pháp dưới đây để sử dụng phương pháp này. Hạn chế duy nhất của phương pháp này là nó có hỗ trợ trình duyệt hạn chế và nó được coi là lỗi thời

cú pháp

Người dùng có thể làm theo cú pháp bên dưới để sử dụng phương thức eval() để gọi hàm

eval( strFunction );

Tương tự như phương thức đối tượng cửa sổ, tên hàm chuỗi được gửi dưới dạng đối số cho phương thức eval()

Thí dụ

Trong ví dụ dưới đây, evalOutput là hàm đầu ra được xác định. Biến toàn cục evalStr lưu trữ hàm này với các tham số dưới dạng chuỗi. Sử dụng cú pháp được giải thích ở trên, eval() gọi giá trị chuỗi này trong biến và chúng ta có hàm đầu ra đang chạy

Using the eval() method to execute function with its string name.

Trong hướng dẫn này, chúng ta đã hiểu hai cách để thực thi hàm JavaScript khi chúng ta có tên của nó là một chuỗi

Phương thức đối tượng cửa sổ là phương thức được sử dụng phổ biến nhất. phương thức eval() không được dùng nữa và không được khuyến nghị

Bạn có thể sử dụng phương thức eval() để gọi một hàm JavaScript có tên được lưu trữ trong một biến chuỗi nhưng có một phương thức tốt hơn không yêu cầu eval

Giả sử chúng ta có một hàm helloWorld(e) lấy biến và in nó

function helloWorld(e) {
  e = e || 'Anonymous';
  console.log('Hello ' + e);
  return;
}

Chúng ta khai báo một biến có tên hàm và một biến khác lưu trữ các đối số

// Function name to invoke
var fnName = 'helloWorld';

// Params to pass to the function
var params = 'ctrlq.org';

// Call function using Window object
window[fnName](params);

Điều này cũng có thể hữu ích để gọi các chức năng của Google Apps Script. Tuy nhiên, vì nó là mã phía máy chủ chứ không phải môi trường trình duyệt web nên chúng tôi sử dụng mã này để chỉ đối tượng chứa mã đó

this[fnName](params);

Javascript

Chia sẻWhatsAppTwitterFacebook

Làm cách nào để gọi một hàm có chuỗi trong JavaScript?

Amit Agarwal

Chuyên gia phát triển của Google, Nhà vô địch Google Cloud

Amit Agarwal là Chuyên gia nhà phát triển của Google về Google Workspace và Google Apps Script. Ông có bằng kỹ sư về Khoa học Máy tính (I. I. T. ) và là blogger chuyên nghiệp đầu tiên ở Ấn Độ

Amit đã phát triển một số tiện ích bổ sung phổ biến của Google bao gồm Mail Merge cho Gmail và Document Studio. Đọc thêm về Lifehacker và YourStory

Cảnh báo. Thực thi JavaScript từ một chuỗi là một rủi ro bảo mật rất lớn. Quá dễ dàng để một kẻ xấu chạy mã tùy ý khi bạn sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5. Xem bên dưới

Hàm

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 đánh giá mã JavaScript được biểu thị dưới dạng chuỗi và trả về giá trị hoàn thành của nó. Nguồn được phân tích cú pháp dưới dạng tập lệnh

eval(script)

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
7

Một chuỗi đại diện cho một biểu thức JavaScript, câu lệnh hoặc chuỗi các câu lệnh. Biểu thức có thể bao gồm các biến và thuộc tính của các đối tượng hiện có. Nó sẽ được phân tích cú pháp dưới dạng tập lệnh, do đó, khai báo

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
8 (chỉ có thể tồn tại trong mô-đun) không được phép

Giá trị hoàn thành của việc đánh giá mã đã cho. Nếu giá trị hoàn thành trống, thì trả về

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
9. Nếu
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
7 không phải là một chuỗi nguyên thủy,
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 trả về đối số không thay đổi

Ném bất kỳ ngoại lệ nào xảy ra trong quá trình đánh giá mã, bao gồm

const expression = new String("2 + 2");
eval(String(expression)); // returns 4
2 nếu
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
7 không thể phân tích cú pháp dưới dạng tập lệnh

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 là thuộc tính chức năng của đối tượng toàn cầu

Đối số của hàm

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 là một chuỗi. Nó sẽ đánh giá chuỗi nguồn dưới dạng phần thân tập lệnh, có nghĩa là cả câu lệnh và biểu thức đều được phép. Nó trả về giá trị hoàn thành của mã. Đối với các biểu thức, đó là giá trị mà biểu thức đánh giá. Nhiều câu lệnh và khai báo cũng có giá trị hoàn thành, nhưng kết quả có thể gây ngạc nhiên (ví dụ: giá trị hoàn thành của một bài tập là giá trị được gán, nhưng giá trị hoàn thành của
const expression = new String("2 + 2");
eval(String(expression)); // returns 4
6 là không xác định), vì vậy bạn không nên dựa vào các câu lệnh'

Ở chế độ nghiêm ngặt, việc khai báo một biến có tên là

const expression = new String("2 + 2");
eval(String(expression)); // returns 4
7 hoặc gán lại
const expression = new String("2 + 2");
eval(String(expression)); // returns 4
7 là một biến
const expression = new String("2 + 2");
eval(String(expression)); // returns 4
2

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode

Nếu đối số của

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 không phải là một chuỗi, thì
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 trả về đối số không thay đổi. Trong ví dụ sau, việc truyền một đối tượng
// Indirect call using the comma operator to return eval
(0, eval)("x + y");

// Indirect call through optional chaining
eval?.("x + y");

// Indirect call using a variable to store and return eval
const geval = eval;
geval("x + y");

// Indirect call through member access
const obj = { eval };
obj.eval("x + y");
2 thay vì một đối tượng nguyên thủy khiến
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 trả về đối tượng
// Indirect call using the comma operator to return eval
(0, eval)("x + y");

// Indirect call through optional chaining
eval?.("x + y");

// Indirect call using a variable to store and return eval
const geval = eval;
geval("x + y");

// Indirect call through member access
const obj = { eval };
obj.eval("x + y");
2 thay vì đánh giá chuỗi

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4

Để giải quyết vấn đề theo cách chung chung, bạn có thể tự mình giải quyết trước khi chuyển cho

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5

const expression = new String("2 + 2");
eval(String(expression)); // returns 4

Có hai chế độ của cuộc gọi

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5. đánh giá trực tiếp và đánh giá gián tiếp. Đánh giá trực tiếp chỉ có một hình thức.
// Indirect call using the comma operator to return eval
(0, eval)("x + y");

// Indirect call through optional chaining
eval?.("x + y");

// Indirect call using a variable to store and return eval
const geval = eval;
geval("x + y");

// Indirect call through member access
const obj = { eval };
obj.eval("x + y");
7 (tên của hàm được gọi là
const expression = new String("2 + 2");
eval(String(expression)); // returns 4
7 và giá trị của nó là hàm toàn cầu
const expression = new String("2 + 2");
eval(String(expression)); // returns 4
7). Mọi thứ khác, bao gồm cả việc gọi nó thông qua biến bí danh, thông qua quyền truy cập thành viên hoặc biểu thức khác hoặc thông qua toán tử chuỗi tùy chọn
function test() {
  const x = 2;
  const y = 4;
  // Direct call, uses local scope
  console.log(eval("x + y")); // Result is 6
  console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
}
0, đều là gián tiếp

// Indirect call using the comma operator to return eval
(0, eval)("x + y");

// Indirect call through optional chaining
eval?.("x + y");

// Indirect call using a variable to store and return eval
const geval = eval;
geval("x + y");

// Indirect call through member access
const obj = { eval };
obj.eval("x + y");

Đánh giá gián tiếp có thể được xem như thể mã được đánh giá trong một thẻ

function test() {
  const x = 2;
  const y = 4;
  // Direct call, uses local scope
  console.log(eval("x + y")); // Result is 6
  console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
}
1 riêng biệt. Điều này có nghĩa là

  • Giá trị gián tiếp hoạt động trong phạm vi toàn cầu thay vì phạm vi cục bộ và mã được đánh giá không có quyền truy cập vào các biến cục bộ trong phạm vi mà nó được gọi

    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    

  • Gián tiếp
    const expression = new String("2 + 2");
    eval(String(expression)); // returns 4
    
    7 sẽ không kế thừa tính nghiêm ngặt của ngữ cảnh xung quanh và sẽ chỉ ở chế độ nghiêm ngặt nếu bản thân chuỗi nguồn có chỉ thị
    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    3

    function strictContext() {
      "use strict";
      eval?.(`with (Math) console.log(PI);`);
    }
    function strictContextStrictEval() {
      "use strict";
      eval?.(`"use strict"; with (Math) console.log(PI);`);
    }
    strictContext(); // Logs 3.141592653589793
    strictContextStrictEval(); // Throws a SyntaxError because the source string is in strict mode
    

    Mặt khác, eval trực tiếp kế thừa tính nghiêm ngặt của ngữ cảnh gọi

    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    

  • function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    Các khai báo hàm và biến được khai báo 4 sẽ đi vào phạm vi xung quanh nếu chuỗi nguồn không được diễn giải ở chế độ nghiêm ngặt - đối với eval gián tiếp, chúng trở thành biến toàn cục. Nếu đó là một eval trực tiếp trong ngữ cảnh chế độ nghiêm ngặt hoặc nếu chính chuỗi nguồn
    const expression = new String("2 + 2");
    eval(String(expression)); // returns 4
    
    7 ở chế độ nghiêm ngặt, thì khai báo hàm
    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    4 và không "rò rỉ" vào phạm vi xung quanh

    // Neither context nor source string is strict,
    // so var creates a variable in the surrounding scope
    eval("var a = 1;");
    console.log(a); // 1
    // Context is not strict, but eval source is strict,
    // so b is scoped to the evaluated script
    eval("'use strict'; var b = 1;");
    console.log(b); // ReferenceError: b is not defined
    
    function strictContext() {
      "use strict";
      // Context is strict, but this is indirect and the source
      // string is not strict, so c is still global
      eval?.("var c = 1;");
      // Direct eval in a strict context, so d is scoped
      eval("var d = 1;");
    }
    strictContext();
    console.log(c); // 1
    console.log(d); // ReferenceError: d is not defined
    

    Các khai báo
    const expression = new String("2 + 2");
    eval(String(expression)); // returns 4
    
    6 và
    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    8 trong chuỗi được đánh giá luôn nằm trong phạm vi tập lệnh đó
  • Đánh giá trực tiếp có thể có quyền truy cập vào các biểu thức theo ngữ cảnh bổ sung. Ví dụ, trong phần thân của hàm, người ta có thể sử dụng
    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    9

    function Ctor() {
      eval("console.log(new.target)");
    }
    new Ctor(); // [Function: Ctor]
    

Sử dụng trực tiếp

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 gặp nhiều vấn đề

  • eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 thực thi mã mà nó được chuyển với các đặc quyền của người gọi. Nếu bạn chạy
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 với một chuỗi có thể bị ảnh hưởng bởi một bên độc hại, bạn có thể sẽ chạy mã độc hại trên máy của người dùng với quyền của trang web/tiện ích mở rộng của bạn. Quan trọng hơn, việc cho phép mã của bên thứ ba truy cập vào phạm vi mà trong đó
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 được gọi (nếu đó là một đánh giá trực tiếp) có thể dẫn đến các cuộc tấn công có thể đọc hoặc thay đổi các biến cục bộ
  • eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 chậm hơn so với các giải pháp thay thế, vì nó phải gọi trình thông dịch JavaScript, trong khi nhiều cấu trúc khác được tối ưu hóa bởi các công cụ JS hiện đại
  • Trình thông dịch JavaScript hiện đại chuyển đổi JavaScript thành mã máy. Điều này có nghĩa là mọi khái niệm về cách đặt tên biến đều bị xóa sạch. Do đó, bất kỳ việc sử dụng
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 nào cũng sẽ buộc trình duyệt thực hiện tra cứu tên biến tốn kém dài để tìm ra vị trí tồn tại của biến trong mã máy và đặt giá trị của nó. Ngoài ra, những điều mới có thể được đưa vào biến đó thông qua
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5, chẳng hạn như thay đổi loại biến đó, buộc trình duyệt phải đánh giá lại tất cả mã máy đã tạo để bù lại
  • Công cụ khai thác từ bỏ bất kỳ quy trình thu nhỏ nào nếu phạm vi phụ thuộc quá độ vào bởi
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5, vì nếu không thì
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 không thể đọc đúng biến trong thời gian chạy

Có nhiều trường hợp việc sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 hoặc các phương pháp liên quan có thể được tối ưu hóa hoặc tránh hoàn toàn

Sử dụng gián tiếp eval()

Hãy xem xét mã này

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
0

Chỉ cần sử dụng eval gián tiếp và buộc chế độ nghiêm ngặt có thể làm cho mã tốt hơn nhiều

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
1

Hai đoạn mã trên dường như hoạt động theo cùng một cách, nhưng chúng thì không;

  • Nó chậm hơn rất nhiều, do kiểm tra phạm vi nhiều hơn. Lưu ý
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    0 trong chuỗi được đánh giá. Trong phiên bản đánh giá gián tiếp, đối tượng đang được đánh giá trong phạm vi toàn cầu, do đó, trình thông dịch có thể giả định rằng
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    1 đề cập đến hàm tạo toàn cầu
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    2 thay vì một biến cục bộ có tên là
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    1. Tuy nhiên, trong mã sử dụng eval trực tiếp, trình thông dịch không thể giả sử điều này. Ví dụ: trong đoạn mã sau,
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    1 trong chuỗi được đánh giá không đề cập đến
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    5

    "use strict";
    
    const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
    
    2

    Do đó, trong phiên bản mã
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5, trình duyệt buộc phải thực hiện cuộc gọi tra cứu tốn kém để kiểm tra xem liệu có bất kỳ biến cục bộ nào được gọi là
    function nonStrictContext() {
      eval(`with (Math) console.log(PI);`);
    }
    function strictContext() {
      "use strict";
      eval(`with (Math) console.log(PI);`);
    }
    nonStrictContext(); // Logs 3.141592653589793
    strictContext(); // Throws a SyntaxError because it's in strict mode
    
    2
  • Nếu không sử dụng chế độ nghiêm ngặt, các khai báo
    function test() {
      const x = 2;
      const y = 4;
      // Direct call, uses local scope
      console.log(eval("x + y")); // Result is 6
      console.log(eval?.("x + y")); // Uses global scope, throws because x is undefined
    }
    
    4 trong nguồn
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 sẽ trở thành các biến trong phạm vi xung quanh. Điều này dẫn đến các vấn đề khó gỡ lỗi nếu chuỗi được lấy từ đầu vào bên ngoài, đặc biệt nếu có một biến hiện có cùng tên
  • eval trực tiếp có thể đọc và biến đổi các liên kết trong phạm vi xung quanh, điều này có thể dẫn đến đầu vào bên ngoài làm hỏng dữ liệu cục bộ
  • Khi sử dụng
    const expression = new String("2 + 2");
    eval(String(expression)); // returns 4
    
    7 trực tiếp, đặc biệt khi nguồn eval không thể được chứng minh là ở chế độ nghiêm ngặt, công cụ — và công cụ xây dựng — phải vô hiệu hóa tất cả các tối ưu hóa liên quan đến nội tuyến, vì nguồn
    eval(new String("2 + 2")); // returns a String object containing "2 + 2"
    eval("2 + 2"); // returns 4
    
    5 có thể phụ thuộc vào bất kỳ tên biến nào trong phạm vi xung quanh của nó

Tuy nhiên, việc sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 gián tiếp không cho phép chuyển các ràng buộc bổ sung ngoài các biến toàn cục hiện có để nguồn được đánh giá đọc. Nếu bạn cần chỉ định các biến bổ sung mà nguồn được đánh giá sẽ có quyền truy cập, hãy cân nhắc sử dụng hàm tạo
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3

Sử dụng hàm tạo Function()

Hàm tạo

// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 rất giống với ví dụ đánh giá gián tiếp ở trên. nó cũng đánh giá nguồn JavaScript được truyền cho nó trong phạm vi toàn cầu mà không cần đọc hoặc thay đổi bất kỳ ràng buộc cục bộ nào và do đó cho phép các công cụ thực hiện nhiều tối ưu hóa hơn so với trực tiếp
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5

Sự khác biệt giữa

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 và
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 là chuỗi nguồn được truyền tới
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 được phân tích dưới dạng thân hàm, không phải dưới dạng tập lệnh. Có một số sắc thái — ví dụ: bạn có thể sử dụng các câu lệnh
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
9 ở cấp cao nhất của thân hàm, nhưng không phải trong tập lệnh

Hàm tạo

// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 rất hữu ích nếu bạn muốn tạo các liên kết cục bộ trong nguồn eval của mình, bằng cách chuyển các biến dưới dạng các liên kết tham số

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
3

Cả

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 và
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 đều đánh giá ngầm mã tùy ý và bị cấm trong cài đặt CSP nghiêm ngặt. Ngoài ra còn có bổ sung an toàn hơn (và nhanh hơn. ) các lựa chọn thay thế cho
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 hoặc
// Neither context nor source string is strict,
// so var creates a variable in the surrounding scope
eval("var a = 1;");
console.log(a); // 1
// Context is not strict, but eval source is strict,
// so b is scoped to the evaluated script
eval("'use strict'; var b = 1;");
console.log(b); // ReferenceError: b is not defined

function strictContext() {
  "use strict";
  // Context is strict, but this is indirect and the source
  // string is not strict, so c is still global
  eval?.("var c = 1;");
  // Direct eval in a strict context, so d is scoped
  eval("var d = 1;");
}
strictContext();
console.log(c); // 1
console.log(d); // ReferenceError: d is not defined
3 cho các trường hợp sử dụng phổ biến

Sử dụng phụ kiện khung

Bạn không nên sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 để truy cập các thuộc tính một cách linh hoạt. Xem xét ví dụ sau trong đó thuộc tính của đối tượng được truy cập không được biết cho đến khi mã được thực thi. Điều này có thể được thực hiện với
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
4

Tuy nhiên,

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 không cần thiết ở đây — trên thực tế, nó dễ bị lỗi hơn, bởi vì nếu
function Ctor() {
  eval("console.log(new.target)");
}
new Ctor(); // [Function: Ctor]
8 không phải là mã định danh hợp lệ, nó sẽ dẫn đến lỗi cú pháp. Ngoài ra, nếu
function Ctor() {
  eval("console.log(new.target)");
}
new Ctor(); // [Function: Ctor]
9 không phải là chức năng bạn kiểm soát, điều này có thể dẫn đến việc thực thi mã tùy ý. Thay vào đó, hãy sử dụng các trình truy cập thuộc tính, nhanh hơn và an toàn hơn nhiều

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
5

Bạn thậm chí có thể sử dụng phương pháp này để truy cập các thuộc tính hậu duệ. Sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5, điều này sẽ giống như

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
6

Việc tránh

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 ở đây có thể được thực hiện bằng cách tách đường dẫn thuộc tính và lặp qua các thuộc tính khác nhau

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
7

Đặt thuộc tính theo cách đó hoạt động tương tự

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
8

Tuy nhiên, hãy lưu ý rằng việc sử dụng các bộ truy cập khung với đầu vào không bị ràng buộc cũng không an toàn — nó có thể dẫn đến các cuộc tấn công tiêm đối tượng

Sử dụng gọi lại

JavaScript có các hàm hạng nhất, nghĩa là bạn có thể chuyển các hàm làm đối số cho các API khác, lưu trữ chúng trong các biến và thuộc tính của đối tượng, v.v. Nhiều API DOM được thiết kế với ý tưởng này, vì vậy bạn có thể (và nên) viết

"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
9

Các bao đóng cũng hữu ích như một cách để tạo các hàm được tham số hóa mà không cần nối các chuỗi

Sử dụng JSON

Nếu chuỗi bạn đang gọi

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 có chứa dữ liệu (ví dụ: một mảng.
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
03), trái ngược với mã, bạn nên xem xét chuyển sang JSON, điều này cho phép chuỗi sử dụng một tập hợp con cú pháp JavaScript để biểu thị dữ liệu

Lưu ý rằng vì cú pháp JSON bị giới hạn so với cú pháp JavaScript, nhiều chữ JavaScript hợp lệ sẽ không phân tích dưới dạng JSON. Ví dụ: không được phép sử dụng dấu phẩy ở cuối trong JSON và tên thuộc tính (khóa) trong ký tự đối tượng phải được đặt trong dấu ngoặc kép. Đảm bảo sử dụng trình nối tiếp JSON để tạo các chuỗi sau này sẽ được phân tích cú pháp dưới dạng JSON

Truyền dữ liệu bị ràng buộc cẩn thận thay vì mã tùy ý nói chung là một ý tưởng hay. Ví dụ: một tiện ích mở rộng được thiết kế để cạo nội dung của các trang web có thể có quy tắc cạo được xác định trong XPath thay vì mã JavaScript

Trong đoạn mã sau, cả hai câu lệnh chứa

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 đều trả về 42. Cái đầu tiên đánh giá chuỗi
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
05;

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
0

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 trả về giá trị hoàn thành của câu lệnh. Đối với
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
08, nó sẽ là biểu thức hoặc câu lệnh cuối cùng được đánh giá

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
1

Ví dụ sau sử dụng

eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 để đánh giá chuỗi
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
10. Chuỗi này bao gồm các câu lệnh JavaScript gán giá trị 42 cho
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
11 nếu
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
12 là năm và gán 0 cho
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
11 nếu ngược lại. Khi câu lệnh thứ hai được thực thi,
eval(new String("2 + 2")); // returns a String object containing "2 + 2"
eval("2 + 2"); // returns 4
5 sẽ khiến các câu lệnh này được thực hiện và nó cũng sẽ đánh giá tập hợp các câu lệnh và trả về giá trị được gán cho
"use strict";

const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
11, bởi vì giá trị hoàn thành của một phép gán là giá trị được gán

Làm cách nào để gọi một hàm có tên là chuỗi trong JavaScript?

Cú pháp. var functionName = "string"; . Here we have stored a string as a function name, and this value is called using window[].

Làm cách nào để gọi một hàm JavaScript từ một chuỗi mà không cần sử dụng eval?

var params = "praveen. khoa học" // Bây giờ hãy gọi hàm mà không sử dụng eval. cửa sổ [fnName](params); Điều này cũng có thể hữu ích để gọi các chức năng của Google Apps Script.

Làm cách nào để biến một chuỗi thành một hàm JavaScript?

Để chuyển đổi một chuỗi thành hàm nên sử dụng phương thức "eval()" . Phương thức này lấy một chuỗi làm tham số và chuyển đổi nó thành một hàm.

3 cách gọi hàm trong JS là gì?

Các hàm trong JavaScript có thể được gọi theo nhiều cách khác nhau. .
Là một chức năng
Là một phương pháp
Là một nhà xây dựng
thông qua cuộc gọi và áp dụng