2013-01-09 11 views
11

Chạy này trong Chrome và Firefox cho câu trả lời khác nhau:Javascript tời kéo trong Chrome và Firefox

(function() { 

     if(true) { 
      function f() { alert("yes"); }; 
     } else { 
      function f() { alert("no"); }; 
     } 
     f(); 

    })(); 

Trong Chrome kết quả là 'không' Trong Firefox kết quả là 'yes'

Tại sao sự khác biệt ?

Trả lời

12

Các hàm khai báo bên trong câu lệnh có điều kiện là không chuẩn, vì vậy không làm điều đó. Đó là một vấn đề đã biết. Bạn có thể sử dụng biểu thức chức năng thay cho tờ khai:

var f; 
if(true) { 
    f = function() { alert("yes"); }; 
} else { 
    f = function() { alert("no"); }; 
} 
f(); 

Các famous Kangax article on function expressions cho một số chi tiết thêm:

FunctionDeclarations chỉ được phép xuất hiện trong Chương trình hoặc FunctionBody. Theo cú pháp, chúng không thể xuất hiện trong Chặn({ ... }) - chẳng hạn như các câu hỏi của if, while hoặc for. Điều này là do Khối chỉ có thể chứa Báo cáo, không phải SourceElements, trong đó FunctionDeclaration là.

Các bài viết tương tự cũng nói:

Đó là đáng nói đến là theo đặc điểm kỹ thuật, triển khai được phép giới thiệu mở rộng cú pháp (xem phần 16), nhưng vẫn có đầy đủ tuân thủ. Đây là chính xác những gì xảy ra trong rất nhiều khách hàng những ngày này. Một số người trong số họ giải thích các khai báo hàm trong các khối như bất kỳ khai báo hàm nào khác - chỉ cần đưa chúng vào đầu phạm vi kèm theo; Khác - giới thiệu ngữ nghĩa khác nhau và tuân theo các quy tắc phức tạp hơn một chút.

5

Từ V8 (Chrome engine JavaScript) bug tracker:

Không phải là một lỗi. Firefox là trình duyệt duy nhất thực hiện những gì bạn mong đợi.

Hành vi của Safari và IE trên ứng dụng này giống với Chrome/V8.

2

Điều này xảy ra do Firefox hay thiếu chức năng cẩu, như hình thành trong ECMAScript 5.

Chrome gán một cách chính xác giá trị cho f() trước khi chạy phần thân của hàm, phiên bản để là người đầu tiên của f() bị ghi đè bởi lần thứ hai.

SpiderMonkey (động cơ Javascript của Firefox) chạy mã mà không pre-assignin một giá trị cho f(), nên sử dụng giá trị duy nhất mà gặp trên đường: function f() { alert("yes"); };

chức năng cẩu là những gì?
Phạm vi chức năng của JavaScript có nghĩa là tất cả các biến được khai báo trong một hàm đều hiển thị trong toàn bộ phần thân của hàm. Thật kỳ lạ, điều này có nghĩa là các biến thậm chí còn có thể hiển thị trước khi chúng được khai báo là . Tính năng này của JavaScript được gọi chính thức là cẩu: Mã JavaScript hoạt động như thể tất cả các khai báo biến trong một hàm (nhưng không phải bất kỳ bài tập nào liên quan đến ) được "hoisted" lên trên cùng của hàm.

nguồn:
http://statichtml.com/2011/spidermonkey-function-hoisting.html
2011 - O'Reilly - javascript - sự dứt khoát dẫn 6 phiên bản