2011-10-13 16 views
7

Tôi đang cố gắng để Shim Element.prototype.children mà phải trả lại một HTMLCollectiontạo HTMLCollection

Có một window.HTMLCollection

Tuy nhiên

var h = new HTMLCollection(); 
//TypeErrror: HTMLCollection is not a constructor 

var h = Object.create(HTMLCollection.prototype); 
h[0] = div; 
h.item(0); 
// Could not convert JavaScript argument 

thử nghiệm Firefox 7 và Chrome

Ngoài việc cắt tỉa HTMLCollection có cách nào để tương tác với nó không?

Cũng cung cấp thông tin phản hồi trên this github issue nếu bạn có thể đề nghị một giải pháp

+0

Tôi tin rằng cách chính xác để làm điều này là xác định hàm tạo MyHTMLCollection' tùy chỉnh của riêng bạn và sau đó sử dụng nó thay vì hàm tạo máy chủ 'HTMLCollection' (không đáng tin cậy) –

+0

Trong khi tôi không thể trả lời câu hỏi cụ thể của bạn về HTMLCollection, nó thường được coi là thực hành xấu để mở rộng các đối tượng DOM (được lưu trữ) gốc. Xem bài viết này để biết giải thích chi tiết tại sao: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – skyline3000

+0

@ skyline3000 Tôi hoàn toàn nhận thức được hậu quả. Chúng ta cần làm điều này để tạo ra một DOM-shim. Chúng tôi không mở rộng DOM với các phương thức tùy chỉnh (điều ác) nhưng với các phương thức nên tồn tại theo đặc tả DOM4 – Raynos

Trả lời

4

Đây là cách tôi sẽ làm điều đó:

function MyHTMLCollection(arr) { 
    for (var i = 0; i < arr.length; i += 1) { 
     this[i] = arr[i]; 
    } 

    // length is readonly 
    Object.defineProperty(this, 'length', { 
     get: function() { 
      return arr.length; 
     } 
    }); 

    // a HTMLCollection is immutable 
    Object.freeze(this); 
} 

MyHTMLCollection.prototype = { 
    item: function (i) { 
     return this[i] != null ? this[i] : null; 
    }, 
    namedItem: function (name) { 
     for (var i = 0; i < this.length; i += 1) { 
      if (this[i].id === name || this[i].name === name) { 
       return this[i]; 
      } 
     } 
     return null; 
    } 
}; 

nơi arr là một mảng thông thường có chứa tất cả các phần tử DOM mà nên bên trong HTMLCollection.

Để làm danh sách:

  • lập luận arr nên được kiểm tra trước: Có một mảng? Có phải tất cả các phần tử của các phần tử DOM mảng đó không?
+0

Còn về 'instance [4] = newEl'. 'length' sẽ thất bại. Tôi nghĩ rằng bạn cần phải tính toán chiều dài ở mỗi nhận được cuộc gọi cho nó để làm việc. – Raynos

+0

@Raynos Tôi vừa cập nhật câu trả lời của mình. 'Object.freeze (this)' bên trong hàm tạo, nhưng tôi không chắc chắn spec nào nói về sự bất biến của các bộ sưu tập HTML. Tôi sẽ kiểm tra ... –

+0

cũng 'Object.defineProperty' chỉ hoạt động trên DOM trong IE8 vì vậy dom-shim của tôi vừa phá vỡ trong IE8. Tôi đoán tôi có thể làm cho thuộc tính 'length' là một giá trị tĩnh trong IE8 và quên nó đi. – Raynos

4

Đừng nghĩ rằng đối tượng máy chủ để hành xử tương tự (ECMAScript) vật bản địa, họ là những thứ hoàn toàn khác nhau. Một số trình duyệt thực hiện các đối tượng DOM của chúng như đối tượng ECMAScript, nhưng nó không bắt buộc và không nên dựa vào. Lưu ý rằng hầu hết các bộ sưu tập HTML đều hoạt động, rất khó để mô phỏng nó trong một đối tượng gốc.

+1

Chúng thực sự cực kỳ khó để mô phỏng mà không có Proxy. – Raynos

0

Tôi biết đây là một câu hỏi cũ nhưng tôi tình cờ gặp một nhu cầu tương tự để tạo ra một HTMLCollection trống rỗng và tôi đã làm nó bằng cách đơn giản tạo ra một phần tử và sau đó chạy getElementsByClassName() chống lại nó bằng một lớp không tồn tại trong phần tử.

document.createElement("div").getElementsByClassName('noClassHere'); 

Trả về đối tượng HTMLCollection trống.

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