2014-09-07 20 views
6

Mọi người đều biết bộ chọn DOM như document.getElementByID(...)document.querySelector(...) làm và cách bạn có thể sử dụng bộ chọn này với các lớp, thuộc tính, id và v.v.QuerySelector hoạt động như thế nào dưới mui xe?

Nhưng tôi không thể tìm thấy nó hoạt động như thế nào dưới mui xe (tôi có thể tìm thấy perf test comparisons nhưng tôi quan tâm đến lý thuyết). Tôi biết rằng trang html được tải, được phân tích bởi trình duyệt và cây DOM được xây dựng. Nhưng làm thế nào để mỗi bộ chọn đi ngang qua cây DOM để tìm các phần tử.

Tôi đã xem xét một số spec for parsing algorithm và đọc thực sự tốt đẹp explanation how Browsers work, nhưng cũng cung cấp giải thích tuyệt vời về HTML, phân tích CSS và luồng hiển thị không giải thích cách mỗi bộ chọn này đi qua cây này để tìm các phần tử.

Tôi giả định rằng để tìm thứ gì đó như .black hoặc span, nó cần phải đi qua toàn bộ cây, nhưng để tìm #id, nó có thể đi qua một số cấu trúc dữ liệu bổ sung và do đó làm cho nó nhanh hơn nhiều. Vui lòng không viết các giả định của bạn, tôi đang tìm kiếm kiến ​​thức cụ thể với bản sao lưu để đặc tả hoặc triển khai trong một số trình duyệt.

+0

Tôi nghĩ điều này sẽ được yêu cầu tốt hơn tại http://programmers.stackexchange.com – spender

+7

Đó là chi tiết triển khai và sẽ khác nhau tùy theo công cụ bạn đang sử dụng. Bạn sẽ phải đọc mã nguồn của việc triển khai khác nhau nếu bạn muốn biết. Xem http://en.wikipedia.org/wiki/List_of_ECMAScript_engines làm điểm bắt đầu. – slashingweapon

+0

@slashingweapon Tôi không thực sự nghĩ như vậy. Đây là một tính năng khá cơ bản và hầu hết có lẽ tôi sẽ được triển khai thực sự tương tự trong các trình duyệt chính. –

Trả lời

6

Kiểm tra Firefox's source và đọc the related documentation sẽ giúp bạn hiểu rõ hơn.
Khi tài liệu được tìm nạp, nó được chuyển đến trình phân tích cú pháp (xem: /mozilla/parser/html/) sẽ nhai qua tài liệu và tạo một cây nội dung. Các phần trung tâm của trình phân tích cú pháp được viết bằng Java (/mozilla/parser/html/javasrc/) và sau đó được dịch sang C++ để xây dựng, vì vậy hãy sẵn sàng để có một thời gian tốt khi bạn muốn đọc phần còn lại của nguồn.

Nhìn vào nguồn của phân tích cú pháp (/mozilla/parser/html/javasrc/TreeBuilder.java), cụ thể là một đoạn trích từ các chức năng startTag:

1579   if (errorHandler != null) { 
1580    // ID uniqueness 
1581    @IdType String id = attributes.getId(); 
1582    if (id != null) { 
1583     LocatorImpl oldLoc = idLocations.get(id); 
1584     if (oldLoc != null) { 
1585      err("Duplicate ID \u201C" + id + "\u201D."); 
1586      errorHandler.warning(new SAXParseException(
1587        "The first occurrence of ID \u201C" + id 
1588        + "\u201D was here.", oldLoc)); 
1589     } else { 
1590      idLocations.put(id, new LocatorImpl(tokenizer)); 
1591     } 
1592    } 
1593   } 

Biến ý đến dòng 1590 và hãy nhớ rằng trước đó trong cùng một tập tin chúng ta có:

459  private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>(); 

Chúng tôi có thể thấy rằng các id nút được lưu giữ trong một bản đồ băm đơn giản. Tra cứu các lớp được xử lý như thế nào là một bài tập được để lại cho người đọc.

Các phương pháp DOM khác nhau, ví dụ document.getElementByID(...), được kết nối với bản đồ băm này thông qua mã keo và rất nhiều phân cấp đối tượng, xem "How is the web-exposed DOM implemented?" on ask.mozilla.org.

+2

Câu trả lời tuyệt vời !! –

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