Tại sao việc mở rộng các nguyên mẫu đối tượng DOM / tích hợp là một ý tưởng tồi?


15

Tôi đang tìm kiếm một câu trả lời dứt khoát về lý do tại sao việc mở rộng các nguyên mẫu tích hợp lại bị trừng phạt nặng nề trong cộng đồng nhà phát triển JS. Tôi đã sử dụng khung công tác Prototype trong một thời gian và đối với tôi, việc này [1,2,3].each(doStuff)có vẻ thanh lịch hơn nhiều so với $.each([1,2,3], doStuff). Tôi biết rằng nó tạo ra "ô nhiễm không gian tên", nhưng tôi không hiểu tại sao nó được coi là một điều xấu. Ngoài ra có bất kỳ sự suy giảm hiệu suất thực tế liên quan đến việc mở rộng các nguyên mẫu tích hợp? Cảm ơn!


1
Một điều là for(var ... in ...)các vòng lặp bị rối vì các chức năng nguyên mẫu cũng được thông qua.
pimvdb

4
"bị trừng phạt nặng nề", thực sự?! trời ơi, anh bạn:] bạn ổn chứ?
pixelbobby

Câu trả lời:


12

Tôi đề nghị bạn đọc bài viết này mà tôi nghĩ giải thích khá rõ tại sao việc mở rộng các đối tượng là một ý tưởng tồi, cũng liên quan đến Prototype.

Tóm tắt:

Thiếu thông số kỹ thuật

Phơi bày của "đối tượng nguyên mẫu" không phải là một phần của bất kỳ đặc điểm kỹ thuật nào. [...] Để việc triển khai tuân thủ đầy đủ DOM Cấp 2, không cần phải phơi bày các đối tượng Node, Element, HTMLEuity, v.v.

Đối tượng máy chủ không có quy tắc

Các đối tượng DOM là các đối tượng máy chủ [...] Các đối tượng máy chủ có thể thực hiện các phương thức bên trong này với bất kỳ hành vi phụ thuộc thực hiện nào hoặc có thể là một đối tượng máy chủ chỉ thực hiện một số phương thức bên trong chứ không phải các phương thức khác.

[...] Hành vi phương thức nội bộ phụ thuộc vào việc thực hiện. [...] Theo định nghĩa, bạn đang làm việc với thứ gì đó được phép hành xử theo cách không thể đoán trước và hoàn toàn thất thường.

Cơ hội va chạm

Với số lượng lớn môi trường được sử dụng ngày nay, không thể biết được liệu một số tài sản nhất định chưa phải là một phần của DOM. [...]

Mỗi thuộc tính bóng điều khiển biểu mẫu được đặt tên được kế thừa thông qua chuỗi nguyên mẫu. Cơ hội va chạm và lỗi không mong muốn trên các yếu tố biểu mẫu thậm chí còn cao hơn.

Sử dụng một số loại chiến lược tiền tố có thể làm giảm bớt vấn đề. Nhưng có lẽ cũng sẽ mang lại thêm tiếng ồn.

Chi phí hoạt động

[...] Các trình duyệt không hỗ trợ các phần mở rộng phần tử, như IE 6, 7, Safari 2.x, v.v., đòi hỏi phải mở rộng đối tượng thủ công. Vấn đề là phần mở rộng thủ công chậm, bất tiện và không có quy mô.

[...] Một khi bạn bắt đầu mở rộng các phần tử, API thư viện rất có thể cần trả về các phần tử mở rộng ở mọi nơi. Kết quả là, các phương thức truy vấn như $$ có thể sẽ mở rộng mọi phần tử đơn lẻ trong một truy vấn.

IE DOM là một mớ hỗn độn

Như đã trình bày trong phần trước, phần mở rộng DOM thủ công là một mớ hỗn độn. Nhưng tiện ích mở rộng DOM thủ công trong IE thậm chí còn tệ hơn [...]

Phần thưởng: lỗi trình duyệt


9

Một lý do khác là khả năng đọc / bảo trì mã. Nếu một nhà phát triển khác (đặc biệt là một người mới) đang đọc mã của tôi và thấy [0, 1, 2].foo(...), họ có thể không biết phương thức foo là gì hoặc nơi tìm tài liệu / nguồn cho nó. Có phải foo là một phần mở rộng cho ngôn ngữ được thêm bởi mẫu.j.j hoặc bởi một thư viện khác đang sử dụng hoặc bởi một phần mã khác của tôi trong một tệp khác, hay đó là một phương thức JavaScript nguyên gốc mà họ không biết? Họ cần phải săn lùng nó và có thể không tìm thấy nó ngay lập tức (hoặc nếu có xung đột, họ có thể không tìm thấy đúng).

Với cách tiếp cận jQuery, nếu bạn thấy $.foo(...), không gian tên của phương thức foo cho thấy rõ nơi tìm định nghĩa / tài liệu của nó nếu bạn không biết nó làm gì.


Khả năng khám phá về phương pháp đến từ đâu là rất quan trọng đối với độc giả. Mặc dù tôi không thực sự nghĩ rằng jQuery là một ví dụ điển hình vì ký hiệu đô la là thử thách tìm kiếm khi bạn đọc mã web và không biết nó là gì.
Simon Feelman

4

Đây là vấn đề cơ bản: Điều gì xảy ra nếu bạn có hai công cụ mở rộng nguyên mẫu theo cách không tương thích hoặc mở rộng các phương thức thường được gọi theo cách mà chúng mang lại kết quả khác nhau (đây là vấn đề cụ thể đối với for...inJavaScript), do đó gây ra mã dựa trên về hành vi bình thường của họ để phá vỡ?

Về cơ bản, đó là những vấn đề tương tự mà bạn gặp phải khi bạn sử dụng sai các biến toàn cục. Chính nó, có lẽ không có gì xấu xảy ra. Tuy nhiên, nó sẽ mở ra cho bạn rắc rối khi hai đoạn mã tách biệt rõ ràng đột ngột giẫm lên nhau (và đó là một nỗi đau để gỡ lỗi khi điều đó xảy ra).

Chắc chắn mẫu.j.j khá nổi tiếng và hầu hết các công cụ đều hoạt động xung quanh những gì nó làm. Tương tự, tôi chắc chắn có những trường hợp mở rộng nguyên mẫu cơ sở là điều nên làm. Nhưng, đó là một cái gì đó để tiếp cận một cách thận trọng.


1

Không chắc đây có thực sự là vấn đề nữa hay không, nhưng trải nghiệm của tôi với các phiên bản Internet Explorer trước đó là đôi khi thậm chí không thể mở rộng các loại tích hợp nhất định.


1

Có hai vấn đề riêng biệt ở đây. Đầu tiên là sự mở rộng chung của các nguyên mẫu tích hợp và cái còn lại đặc biệt là mở rộng các nguyên mẫu DOM. Các đối số chống lại việc mở rộng các nguyên mẫu tích hợp:

  • Xung đột tiềm năng: hai đoạn mã từ các nguồn khác nhau đều xác định cùng một thuộc tính trên cùng một nguyên mẫu
  • Tác dụng phụ: mở rộng Array.prototypehoặc Object.prototypecó thể có các hiệu ứng kích thích, chẳng hạn như thêm các phương thức mở rộng được liệt kê trong một for...invòng lặp

Đối với việc mở rộng các nguyên mẫu DOM, đối số xung đột tiềm năng ở trên vẫn được áp dụng. Ngoài ra, các nút DOM là các đối tượng máy chủ và do đó không phải tuân theo bất kỳ quy tắc thông thường nào của các đối tượng JavaScript gốc. Về cơ bản, họ có thể làm những gì họ thích và không có nghĩa vụ phải cung cấp các đối tượng nguyên mẫu hợp lý hoặc thậm chí cho phép các thuộc tính bổ sung ("bung nở"). IE đặc biệt thực hiện quyền này, không cung cấp nguyên mẫu cho các đối tượng DOM trước IE 9 và có nhiều điểm kỳ lạ khác nhau về các thuộc tính trên các đối tượng DOM khác nhau (mặc dù bạn thường gán các thuộc tính cho các phần tử, không cung cấp gì được đặt document.expandothành false.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.