2009-09-12 30 views
7

Tôi có một hàm javascript không chạy và đã ném một lỗi. Mất khoảng một giờ để nhận ra rằng biểu mẫu của tôi có cùng tên với chức năng. Có vẻ kỳ quặc rằng một tên mẫu sẽ xung đột với tên hàm, nhưng tôi vẫn đổi tên và mọi thứ hoạt động tốt. Có ai biết tại sao điều này thậm chí sẽ xảy ra?Javascript Chức năng và Tên Biểu mẫu xung đột

Nếu bạn chạy mã này nó sẽ thất bại, nhưng nếu bạn thay đổi tên biểu mẫu nó hoạt động, rất lạ.

<html> 
<head> 
<title>Untitled Document</title> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
<script type="text/javascript"> 
function mytest(){alert("hello");} 
</script> 
</head> 
<body> 
<form name="mytest" ></form> 
<a href="#" onClick="mytest();">Click Me</a> 
</body> 
</html> 

Tôi đang chạy tính năng này trên IE6. Điều lạ lẫm đối với tôi là mã JavaScript là mã Javascript và cái kia là thuộc tính của HTML.

Live link nơi bạn có thể thấy điều này xảy ra:
JSBin

+0

Tôi đã tìm thấy liên kết này giải thích nó cũng http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html –

Trả lời

6

Chức năng là thành viên trong đối tượng window, và dưới hình thức là một thành viên của forms bộ sưu tập trong đối tượng document. Khi tập lệnh tìm kiếm kết quả phù hợp cho từ định danh "mytest", đầu tiên nó sẽ tìm đối tượng document và nếu không tìm thấy nó ở đối tượng window.

Bạn có thể truy cập vào các chức năng ngay cả với tên mẫu xung đột nếu bạn xác định rằng đó là trong đối tượng window:

<a href="#" onClick="window.mytest();">Click Me</a> 
+2

Nó cũng phụ thuộc vào trình duyệt. IE gây ô nhiễm không gian tên chung với các thành viên cho mọi phần tử trên trang khai báo một ID hoặc một thuộc tính NAME. Không cần phải nói nó gây ra rất nhiều vấn đề. Điều đó nói rằng do cần hỗ trợ IE trong hầu hết các trường hợp, bạn tốt nhất nên thử và đảm bảo rằng tên hàm của bạn sẽ không va chạm với các giá trị tên/id của các phần tử trong trang của bạn. – scunliffe

+0

@Scunliffe: Trên thực tế trong trường hợp này các trình duyệt khác bị ảnh hưởng. Cũng lưu ý rằng IE ưu tiên cho các tên được định nghĩa trong javascript. Chỉ khi tìm kiếm javascript tiêu chuẩn cho một tên trong phạm vi quay lên với không có gì IE cố gắng để giải quyết một tên theo cách bạn đề nghị. Do đó, trường hợp thử nghiệm trong ví dụ sẽ không thành công. – AnthonyWJones

7

Để thêm một số chi tiết với những gì đang xảy ra ở đây bạn cần phải hiểu chuỗi phạm vi javascript của.

Phạm vi đối tượng

Một đối tượng phạm vi là một đối tượng ẩn tạo ra khi một chức năng được thực thi trên đó các biến khai báo với var được đặt như tài sản, cũng có tên là function bên trong hàm thực hiện cũng được đặt như tài sản trên đối tượng phạm vi.

Khi số nhận dạng như mytest được yêu cầu tìm kiếm javascript cho tên đó được gắn với đối tượng phạm vi hiện tại (btw đối tượng phạm vi còn được gọi là "ngữ cảnh thực thi").

Phạm vi chuỗi

Khi một hàm được khai báo bên trong một hàm đối tượng phạm vi hiện được gắn vào hàm. Khi hàm bên trong này đang thực hiện (và do đó có đối tượng phạm vi riêng của nó), việc thực thi mã có quyền truy cập không chỉ đối tượng phạm vi hiện tại mà còn đối tượng phạm vi mà chức năng hiện đang thực hiện được tạo ra. Dừng ở đây, Đọc lại câu cuối cùng. Điều này được gọi là chuỗi phạm vi , chuỗi sẽ sâu như có các hàm bên trong các hàm (điều này xảy ra rất nhiều khi sử dụng các khung công tác như JQuery).

Do đó khi tìm kiếm số nhận dạng không thành công trên đối tượng phạm vi hiện tại, nó sẽ xem xét đối tượng phạm vi tiếp theo trong chuỗi. Nó tiếp tục đi lên chuỗi cho đến khi nó chạm vào đối tượng toàn cầu (các hàm được khai báo ở mức toàn cục có đối tượng toàn cục như đối tượng phạm vi của chúng).

Sự kiện Thuộc tính weirdness

Khi trình duyệt thực thi mã bên trong văn bản của một thuộc tính như onclick nó đối xử với mã này như thể nó là một hàm. Tuy nhiên các trình duyệt sẽ làm những điều kỳ lạ với chuỗi phạm vi rõ ràng gắn liền với "chức năng" này. Thông thường chúng tiêm phần tử hiện tại và phần tử tài liệu (và có thể các phần tử khác ở giữa) như thể chúng là các đối tượng phạm vi vào trong chuỗi phạm vi.

Ví dụ: thay đổi mã onclick trong ví dụ của bạn thành "alert (href)". Bạn sẽ thấy đường dẫn đến trang của mình theo sau là # trong hộp cảnh báo. Điều này là do phần tử hiện tại nằm trong chuỗi phạm vi và do đó href được giải quyết bởi thuộc tính href của nó.

Trong trường hợp trong câu hỏi, mã đến tại số document trong chuỗi phạm vi (được đặt phía trên đối tượng cửa sổ chung) và tìm mã định danh "mytest" (tham chiếu đến biểu mẫu) và do đó cố gắng sử dụng giá trị của nó như một hàm (và thất bại).

+0

Giải thích hay, Anthony. Điều duy nhất tôi sẽ thay đổi là đổi tên những gì bạn gọi là "đối tượng phạm vi" thành "Đối tượng biến" (đó là những gì nó thực sự là :)). Một điều khác gây hiểu nhầm là "hàm được đặt tên" là thành viên của đối tượng Biến. Họ không phải. Các khai báo hàm là, nhưng, nói, các biểu thức hàm không, nhưng chúng cũng có thể được "đặt tên" (iow, có định danh). Và cuối cùng, bất kỳ ai quan tâm đến các vấn đề về phạm vi của các cơ quan xử lý sự kiện nội tại, nên đọc bài viết này (http://www.jibbering.com/faq/names/event_handler.html) để tìm hiểu chi tiết về chủ đề này :) – kangax

+0

@Kangax: Cảm ơn bạn đã bình luận. Có Tôi đồng ý rằng nghiêm chỉnh nói ECMA 262 sử dụng thuật ngữ "Đối tượng biến" nhưng nó là IMO một tên câm vì nó ngụ ý rằng một số "đối tượng" "khác nhau" trong một số cách. Thuật ngữ này chỉ có ý nghĩa trong bối cảnh của spec đó là tốt cho người triển khai giải thích điều này với một máy tính nhưng rác cho hiểu của con người. Thuật ngữ "Phạm vi đối tượng" đứng trên riêng của nó và ngụ ý rằng có một số đối tượng liên quan đến Phạm vi, nó cũng dễ dàng để lý do rằng nó có khả năng được liên kết với điều khác được gọi là một "chuỗi phạm vi". – AnthonyWJones

+0

@Kangax: Theo như "chức năng được đặt tên" có liên quan Tôi không chắc chắn tôi làm theo lý do của bạn. Bạn dường như nói rằng bạn có thể đặt tên một biểu thức hàm mà không có tên đó kết thúc trên đối tượng Variable nhưng tôi không chắc chắn đó là những gì bạn thực sự có nghĩa là mặc dù. – AnthonyWJones

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