2013-07-21 31 views
6

javascript có cho phép đánh dấu bí danh không? Phần đầu tiên của mã sau hoạt động không mong muốn (hiển thị 1, 1), nhưng phần thứ hai không (hiển thị 1, 2). Tham chiếu đến tập lệnh ECMA hoặc tài liệu mozilla sẽ hữu ích, tôi không thể tìm thấy tài liệu này.Javascript eval alias

<html> 
<script type="application/javascript;version=1.8"> 
    (function(){ 
     eval('var testVar=1'); 
     alert(testVar); 
     var eval2=eval; 
     eval2('var testVar=2'); 
     alert(testVar); 
    })(); 

    (function(){ 
     eval('var testVar=1'); 
     alert(testVar); 
     eval('var testVar=2'); 
     alert(testVar); 
    })(); 
</script> 
</html> 
+1

Kết quả đầu tiên của bất ngờ là như thế nào? –

+0

Khi 'eval' không được đặt bí danh, nó sẽ hiển thị 1, 2, xem hàm thứ hai. Nếu được mong đợi, bạn có thể trả lời câu hỏi này không? Cảm ơn. – simonzack

+0

Có nhưng bạn đã nói hành động đầu tiên hoạt động bất ngờ bằng cách hiển thị 1 và 2. Điều đó được mong đợi. –

Trả lời

7

Bạn không thể "bí danh" eval và mong đợi nó hoạt động như cũ. Đơn giản như thế. Tại sao? eval không phải là một chức năng.

Điều đang xảy ra là khi bạn gọi eval2, bạn đang đặt biến "bộ nhớ cache" để làm việc với các biến toàn cầu. Vì vậy, bằng cách thiết lập một biến bên trong nó, bạn đang thiết lập một biến toàn cục. Tuy nhiên, khi thoát, biến "cache" trả về hàm scoped một. Đó là lý do tại sao số alert thứ hai hiển thị 1 - biến toàn cầu đang bị che khuất bởi hàm mức hàm.

này được ghi nhận trong Phụ lục E (trang 239) của ECMAScript (tôi nhấn mạnh)

10.4.2: Trong phiên bản 5, cuộc gọi gián tiếp đến chức năng eval sử dụng môi trường toàn cầu như cả môi trường biến đổi và môi trường từ vựng cho mã eval. Trong phiên bản 3, các môi trường biến và từ vựng của người gọi của một eval gián tiếp được sử dụng làm môi trường cho mã eval.

Định nghĩa đầy đủ về "Bước vào Eval Code" được định nghĩa trong §10.5.2 (trang 58) (tôi nhấn mạnh)

  1. Nếu không có bối cảnh gọi điện thoại hoặc nếu mã eval không phải là được đánh giá bởi một cuộc gọi trực tiếp (15.1.2.1.1) đến hàm eval sau đó,
    • Khởi tạo bối cảnh thực hiện như thể nó là một bối cảnh thực hiện toàn cầu sử dụng mã eval như C như mô tả trong 10.4.1.1 .
  2. khác,
    • Đặt ThisBinding với giá trị tương tự như ThisBinding của bối cảnh thực hiện gọi điện thoại.
    • Đặt LexicalEnvironment thành cùng giá trị với LexicalEnvironment của ngữ cảnh thực thi cuộc gọi .
    • Đặt VariableEnvironment thành cùng giá trị với VariableEnvironment của ngữ cảnh thực thi cuộc gọi .
  3. Nếu mã eval là mã nghiêm ngặt, sau đó
    • Hãy strictVarEnv thể là kết quả của việc gọi NewDeclarativeEnvironment đi qua các LexicalEnvironment làm đối số.
    • Đặt LexicalEnvironment thành strictVarEnv.
    • Đặt VariableEnvironment thành strictVarEnv.
  4. Thực hiện ràng buộc ràng buộc khai báo như được mô tả trong 10.5 sử dụng mã eval.
+1

Nếu 'eval' không phải là một hàm, tại sao' alert (eval) 'hiển thị' hàm eval() {[native code]} '? – Teemu

+0

Phần đầu tiên của bạn không chính xác, bí danh 'eval' hoạt động trong firefox và không có lỗi nào được nêu ra, nhưng không phải như tôi mong đợi. Hãy thử 'eval2 (alert (" test "))'. Trong thực tế, thông số ECMA nói "Việc triển khai không còn được phép hạn chế việc sử dụng eval theo cách không phải là cuộc gọi trực tiếp. Ngoài ra". – simonzack

+3

Bạn đang hiểu sai tiêu chuẩn. 'eval' * có thể * được đặt bí danh, nhưng sau đó nó sẽ hoạt động khác nhau. Xem các phần khác của tiêu chuẩn: "* Mã đánh giá là văn bản nguồn được cung cấp cho hàm tích hợp sẵn **. ***" (# 10.1), "* hoặc nếu mã eval không được đánh giá bởi dấu * * gọi trực tiếp *** "(# 10.4.2) và các cuộc gọi khác. – DCoder

2

Trong trường hợp đầu tiên khi bạn sử dụng eval, nó sử dụng phạm vi chức năng mà nó được thực thi. Khi bạn gán eval cho eval2 và sau đó thực hiện cùng một câu lệnh, có vẻ như bạn đang sử dụng ngữ cảnh window (phạm vi toàn cục) chứ không phải ngữ cảnh chức năng. Đó là lý do tại sao bạn thấy cùng một giá trị 1 trong trường hợp đầu tiên vì testVar bên trong hàm là 1 và ngoài window.testVar là 2. Bạn có thể chứng minh điều này bằng cách thực hiện dưới đoạn mã

<script> 
(function(){ 
     eval('var testVar=1'); 
     alert(window.testVar); 
     var eval2=eval; 

     eval2('var testVar=2'); 
     alert(window.testVar); 
    })(); 

    (function(){ 
     eval('var testVar=1'); 
     alert(testVar); 
     eval('var testVar=2'); 
     alert(testVar); 
    })(); 
</script> 

Trên thực tế, theo Mozilla Developer Network, bạn có thể' t alias eval.

Các vấn đề liên quan