2012-04-27 34 views
28

document.all là một đối tượng không nguyên thủy trong DOM bị lỗi.Tại sao tài liệu lại bị sai?

Ví dụ, mã này không làm bất cứ điều gì:

if (document.all) { 
    alert("hello"); 
} 

Ai đó có thể giải thích tại sao điều này là gì?

+0

Trình duyệt hiện tại không thực hiện điều lỗi thời này nữa. Đó là một "tiêu chuẩn" IE, Opera cũng "shims" nó. – Bergi

+0

@Nanne câu hỏi là: ai đó có thể giải thích, tại sao mã không làm gì cả. Nếu nó không được thực hiện, nếu sẽ là sai và không có gì sẽ xảy ra. Vì vậy, tôi nghĩ, đó là câu trả lời. –

+0

Nhưng câu hỏi cũng nói rằng chúng ta đang đối phó với một đối tượng không null? Có lẽ tôi đã đọc sai, nhưng tôi cho rằng điều đó có nghĩa là trong bài kiểm tra nó ở đó, nhưng không kích hoạt? – Nanne

Trả lời

2

document.all không phải là đối tượng duy nhất bị lỗi. Một câu hỏi khác đã được đăng về điều này và như ví dụ fiddle trong câu trả lời cho thấy có nhiều đối tượng giả trong tài liệu. Số tiền khác nhau tùy thuộc vào trình duyệt được sử dụng.

Xem câu hỏi này All objects in JavaScript are truthy per the spec, but in the DOM one non-primitive object is not. Which?

Và một fiddle hiển thị tất cả các đối tượng falsy của tài liệu http://jsfiddle.net/UTNkW/

+3

Bài kiểm tra bạn đã liên kết không chính xác theo nhiều cách khác nhau. Chúng tôi chỉ đang tìm kiếm những vật thể không nguyên thủy bị giả mạo. Thử nghiệm của bạn trả về rất nhiều giá trị 'null'. Xem http://stackoverflow.com/questions/10348995/all-objects-in-javascript-are-truthy-per-the-spec-but-in-the-dom-one-non-primit/10349366#comment13404885_10351511. –

4

Trình duyệt hiện tại không thực hiện điều lỗi thời này nữa. Nó đã được giới thiệu bởi IE, nhưng hầu hết những người khác "shim" nó tương thích.

Để làm cho khả năng phát hiện trình duyệt (trở lại những ngày cũ, bạn có thể nói với IE ngoài NN bằng cách kiểm tra document.all) trong khi hỗ trợ cú pháp document.all, các trình duyệt khác đã thực hiện "lạ" typeof document.all trả về không xác định.

Opera> document.all 
// prints the array-like object 
Opera> typeof document.all 
"undefined" 
Opera> Boolean(document.all) 
false 

Trước khi FF bỏ hỗ trợ cho nó, nó cũng cho thấy hành vi lạ như đã nêu trong this message. Bạn có thể tìm thêm nội bộ trong số Mozilla bug #412247.

Ngoài ra còn có một very long thread trong kho lưu trữ danh sách gửi thư của W3C, bắt đầu với http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html

73

Disclaimer:I’m the guy who tweeted the question that led to this thread :) Đó là một câu hỏi tôi sẽ hỏi và trả lời trong Front-Trends nói chuyện của tôi. Tôi đã viết tweet đó 5 phút trước khi lên sân khấu.


Câu hỏi tôi đã hỏi là như sau.

Các ECMAScript đặc tả defines ToBoolean() as follows:

ToBoolean(condition), slide from my Front-Trends 2012 talk

Như bạn có thể thấy, tất cả đối tượng phi nguyên thủy (tức là tất cả các đối tượng mà không phải là một boolean, một số, một chuỗi, undefined, hoặc null) là sự thật theo spec. Tuy nhiên, trong DOM, có một ngoại lệ cho điều này - một đối tượng DOM bị lỗi. Bạn có biết cái nào?

Câu trả lời là document.all. The HTML spec nói:

Thuộc tính all phải trả lại một HTMLAllCollection bắt rễ tại Document nút, có bộ lọc phù hợp với tất cả các yếu tố này.

Đối tượng được trả về cho tất cả có một số hành vi bất thường:

Các user agent phải hành động như thể ToBoolean() điều hành trong JavaScript chuyển đổi đối tượng được trả về cho all với giá trị false.

Các user agent phải hành động như thể, đối với các mục đích của ==!= nhà khai thác trong JavaScript, đối tượng được trả về cho all là bằng giá trị undefined.

Các user agent phải hành động như vậy mà typeof điều hành trong JavaScript trả về chuỗi 'undefined' khi áp dụng cho các đối tượng được trả về cho all.

Các yêu cầu này là một sự vi phạm cố ý của JavaScript đặc điểm kỹ thuật hiện tại tại thời điểm viết (ấn bản ECMAScript 5). Đặc tả JavaScript yêu cầu toán tử ToBoolean() chuyển đổi tất cả các đối tượng thành giá trị true và không có quy định cho các đối tượng hoạt động như thể là undefined cho mục đích một số toán tử nhất định. Vi phạm này được thúc đẩy bởi khả năng tương thích với hai lớp nội dung cũ: một mức sử dụng sự hiện diện của document.all như một cách để phát hiện tác nhân người dùng cũ và . mà không kiểm tra sự hiện diện của nó trước.

Vì vậy, document.all là ngoại lệ chính thức duy nhất cho quy tắc ECMAScript này. (Trong Opera, document.attachEvent vv cũng bị sai, nhưng không được xác định ở bất kỳ đâu.)

Văn bản trên giải thích lý do tại sao điều này được thực hiện. Nhưng đây là một ví dụ đoạn mã đó là rất phổ biến trên các trang web cũ, và điều đó sẽ minh họa điều này nữa:

if (document.all) { 
    // code that uses `document.all`, for ancient browsers 
} else if (document.getElementById) { 
    // code that uses `document.getElementById`, for “modern” browsers 
} 

Về cơ bản, trong một thời gian dài document.all được sử dụng theo cách này để phát hiện các trình duyệt cũ. Bởi vì document.all được thử nghiệm trước tiên, mặc dù các trình duyệt hiện đại hơn cung cấp cả hai thuộc tính, sẽ vẫn kết thúc trong đường dẫn mã document.all. Trong các trình duyệt hiện đại, chúng tôi muốn sử dụng document.getElementById, tất nhiên, nhưng vì hầu hết các trình duyệt vẫn có document.all (vì các lý do tương thích ngược khác), else sẽ không bao giờ được truy cập nếu document.all là trung thực. Nếu mã được viết khác đi, điều này sẽ không thành vấn đề:

if (document.getElementById) { 
    // code that uses `document.getElementById`, for “modern” browsers 
} else if (document.all) { 
    // code that uses `document.all`, for ancient browsers 
} 

Nhưng thật đáng buồn, rất nhiều mã hiện có theo cách khác.

Sửa chữa đơn giản nhất cho vấn đề này đơn giản là làm cho document.all trở nên sai trong các trình duyệt vẫn bắt chước.

+3

Câu trả lời khá có liên quan cho một tính năng lỗi thời. – adrianp

+9

@adrian Chào mừng bạn đến với trang web, nơi mọi thứ trở nên phức tạp vì các tính năng cũ :) –

0

Ok, hãy gọi cho tôi là @@@, bỏ phiếu cho tôi và nghĩ tôi là dị giáo, nhưng vì jQuery đã giảm $ .browser Tôi đã khởi động lại bằng cách sử dụng trình duyệt này để phát hiện trình duyệt nhanh và bẩn.

Hãy để tôi giải thích lý do tại sao và khi nào: Tôi không muốn kiểm tra xem phiên bản cụ thể (phụ) của IE có hỗ trợ gì hay không, tôi cũng không muốn thêm plugin hoặc chức năng tùy chỉnh không phải lúc nào cũng hoạt động hoặc cần được cập nhật hoặc thậm chí thay thế mỗi khi Microsoft phát hành bản cập nhật, tôi chỉ muốn biết nếu tôi cần thêm một setTimeout vào hàm init của mình để tránh IE bị treo hoặc đóng băng và không muốn làm tê liệt các trình duyệt đáng tin cậy hơn trong quá trình này. Hãy trung thực, tất cả chúng ta đều biết rằng Microsoft sẽ KHÔNG BAO GIỜ bỏ nó (để tương thích ngược với các ứng dụng web công ty lớn chỉ dựa trên IE, có thể Chúa tha thứ cho họ) và các nhà cung cấp trình duyệt khác sẽ theo dõi. kể từ cái chết (không-không-được-không-được) của Netscape.

Và IMHO, đó cũng là một hành vi HTML5 tuân thủ;)

+0

Microsoft đã thực sự "bỏ nó" - chúng đã tạo ra tài liệu. Tất cả đều có trong IE 11. http://www.nczonline.net/ blog/2013/07/02/internet-explorer-11-dont-gọi-me-ie/ –

+0

oh, drat! tôi cần phải thay đổi nó từ document.all thành document.all [0], tôi nghĩ rằng tôi đang thêm lib hiện đại ở khắp mọi nơi và reengineer mọi thứ. :) – Dariozzo

+0

btw: nó không lịch sự để chế giễu tiếng anh xấu của một ai đó khi bạn thực sự có thể nói chỉ của bạn. – Dariozzo

5

Nói tóm lại, nó là phải đảm CẢ của các mã mẫu làm việc. Trình duyệt phải thực hiện việc này để các trang web cũ sẽ tiếp tục hoạt động.

Sample 1

// Internet Explorer 
if (document.all) { 
    useActiveX() 
} 
// Netscape Navigator 
else { 
    useOldButStillWorkingCode() 
} 

Sample 2

document.all.output.innerHTML = 'Hello, world!' 
Các vấn đề liên quan