JavaScript khi Object được tạo từ hư vô

Một ngày đẹp trời, tôi cần kiểm tra các thuộc tính của một đối tượng trước khi thực hiện một số hành động khác. Theo thông lệ từ khi còn đi học, cú pháp phổ biến obj.hasOwnProperty sẽ được sử dụng, trả về true nếu obj của chúng ta thực sự có thuộc tính đó và trả về falsetrong. nếu không thì. Tuy nhiên, cú pháp này được báo cáo bởi ESlint (một công cụ linting trong JavaScript mà các công ty thường sử dụng). Hãy thử ví dụ sau:

Với ESlint, dòng code trên không phải là “chuẩn”, một khi nó không được chỉnh sửa thì nó sẽ không được dùng để xây dựng dự án. Lỗi ở đây:

ESlint phân loại lỗi trên là “Không cho phép sử dụng trực tiếp các nội trang Object.prototypes (no-prototype-builtins)”. Phải sửa những điều sau:

Lưu ý rằng Object khác với obj. Hình trên mình viết là object thì vẫn đúng nhưng để dễ phân biệt thì trong bài này mình đã đổi thành obj (còn ảnh thì tạm thời lười quá).

Tại sao ESlint lại bắt được lỗi “no-prototype-builtins” ở trên?

Thấy lỗi này khá kỳ quặc, tôi tra cứu tài liệu ESlint và thấy họ viết như sau:

Trong ECMAScript 5.1, Object.create đã được thêm vào, cho phép tạo các đối tượng với một [[Prototype]]. Object.create (null) là một mẫu phổ biến được sử dụng để tạo các đối tượng sẽ được sử dụng như một Bản đồ. Điều này có thể dẫn đến lỗi khi giả định rằng các đối tượng sẽ có thuộc tính từ Object.prototype. Quy tắc này ngăn không cho gọi các phương thức Object.prototype trực tiếp từ một đối tượng.

Dịch sát nghĩa là:

Kể từ ECMAScript 5.1, Đối tượng có thể được tạo bằng cú pháp Object.create (). Đối tượng mới tạo sẽ có thuộc tính __proto__, thuộc tính này sẽ là đối tượng (đối tượng bên trong đối tượng) hoặc null, tùy thuộc vào tham số được truyền vào lúc gọi Object.create () của lập trình viên. Từ đây nảy sinh lập trình viên sử dụng Object.create (null) để tạo một Bản đồ (cũng là một kiểu đối tượng, nhưng cụ thể hơn). Điều này có khả năng dễ xảy ra lỗi vì thông thường nếu chúng ta không phải là tác giả của mã gốc, chúng ta sẽ giả định rằng: “nếu chúng ta là đối tượng, chúng ta sẽ có thuộc tính (tức là thuộc tính) từ Object.prototype, vì vậy hãy thử gọi các phương thức của Object.prototype “trực tiếp, dẫn đến lỗi. Điều khoản này (của ESlint) cho phép ngăn ngừa các lỗi như vậy.

Đoạn trên không hiểu gì cả! Điều duy nhất chúng tôi biết là ESlint nghĩ rằng chúng tôi không nên viết mã như thế này:

nên được viết là:

Được rồi, cứ như vậy đi. Vậy tạo đối tượng thông qua Object.create () nghĩa là như thế nào? Và cả Object.create (null) !!!

Mình nghĩ bạn cần xem =>  Wifi là gì mà ai ai cũng săn tìm, kết nối

Thông thường, chúng ta được dạy hai cách sau để tạo các đối tượng:

• 1 là sử dụng toán tử mới với hàm tạo đối tượng: new Object (). Cách này cá nhân tôi ít sử dụng.

• 2 là sử dụng một đối tượng theo nghĩa đen (là hai dấu ngoặc nhọn {}), ví dụ: xeHonda = {type: “AirBlade”}.

Hóa ra vẫn còn một cách nữa, đó là sử dụng Object.create (). Bạn có thể xem chi tiết cách sử dụng Object.create () tại đây Đây, và một số lợi thế của nó là ở đây.

Trong bài viết này, chúng tôi chỉ tập trung vào Object.create (null). Hãy dùng thử trong Chrome Devnhé:

Kiểm tra xem mỗi đối tượng chứa những gì?

Lạ đúng không !!! obj1 = Object.create (null) tạo một đối tượng rỗng không có thuộc tính nào cả. Bạn obj2 nghĩ rằng nó cũng rỗng, nhưng vẫn có một thuộc tính tên __proto__ được sinh ra. Điều đó có nghĩa là gì?

• Tất cả các đối tượng được tạo bằng JavaScript đều có ít nhất 1 thuộc tính tên __proto__ với các thuộc tính và phương thức được kế thừa từ tổ tiên là Object, bạn không cần khai báo gì thêm.

• Trường hợp ngoại lệ xảy ra khi bạn truyền tham số null như trên, lúc này đối tượng của chúng ta thực sự rỗng vì nó không kế thừa từ bất cứ thứ gì.

Nếu vậy thì Object.create (null) được sinh ra để làm gì?

Liệu những người viết ECMAScript có rảnh không? Bản thân tôi không có câu trả lời cho câu hỏi này. Nhưng David Walsh (một lập trình viên người Mỹ cho Mozilla) đã viết trong bài báo Object.create (null) như sau:

Object.create là một cách tuyệt vời để tạo các đối tượng với nguyên mẫu. Nhưng vấn đề là nó tạo ra __proto__ kế thừa tất cả các thuộc tính từ Object tổ tiên, có thể được thao tác hoàn toàn bằng thao tác. Bạn sẽ làm gì nếu bạn chỉ muốn tạo một đối tượng mới và giữ cho nó không bị sửa đổi bên ngoài? Bạn có thể đạt được điều này với Object.create (null).

Xem đoạn mã sau:

Theo Davis Walsh, anh ta không muốn tạo một đối tượng có tên là obj, và sau đó, obj “đột nhiên” phát triển một phương thức sayHello chỉ vì “ở đâu đó” ai đó đã thay đổi Object gốc thông qua Object.prototype.

Khi obj được tạo bằng Object.create (null), nó không còn nguyên mẫu để được kế thừa từ Object. Hãy dùng thử:

Và Dmitry Pashkevich (cũng là một lập trình viên người Mỹ làm việc cho Lucid Chart) trong bài viết Object.create (null) đã khẳng định thêm ý tưởng của David Walsh ở trên:

Đôi khi bạn muốn sử dụng một đối tượng JavaScript làm bản đồ băm (chỉ đơn giản là lưu trữ dữ liệu), thì bạn sẽ cần một đối tượng được tạo từ Object.create (null).

Mình nghĩ bạn cần xem =>  Dark data - Khái niệm dữ liệu tưởng mới mà không mới

Đối tượng này khác với đối tượng được tạo từ var data = {} ở chỗ bạn sẽ nhận được một đối tượng sạch, không kế thừa từ bất cứ thứ gì (tức là không có nguyên mẫu). Ưu điểm? Không có thuộc tính, không có hàm tạo, không có toString, không có hasOwnProperty, v.v. nên bạn có thể tự do sử dụng các Key mình cần.

Tất nhiên, ngay cả với các đối tượng thông thường thuộc loại var data = {}, bạn không nên chạm vào các từ Key được JavaScript sử dụng. Nhưng điều gì sẽ xảy ra nếu bạn cần xây dựng một tập hợp các phần tử (ở dạng bản đồ) với các Key ngẫu nhiên do người dùng nhập hoặc từ các API của bên thứ ba? Đây là nơi Object.create (null) được sử dụng!

Ngoài Object.create (null) và “map”, nó là gì?

Theo Nhà phát triển Mozilla, các đối tượng kiểu bản đồ chứa một hoặc nhiều cặp “Key-giá trị”. Khóa và giá trị có thể mang bất kỳ giá trị nào (dù là đối tượng hay giá trị nguyên thủy). Thông tin chi tiết về mặt hàng này tại đây. Do phần bản đồ dài nên sẽ không trình bày hết ở đây. Ngoài tài liệu tiếng Anh trên, có một tài liệu tham khảo bằng tiếng Việt trên freetuts tên là Collection Maps trong ES6 tương đối dễ hiểu.

ESlint đã cập nhật quy định trên như thế nào?

Sau một thời gian phân tích, chúng ta hẳn đã nhận ra mô tả tại sao ESlint chặn mã hóa thông thường. Tuy nhiên, khi đọc thảo luận của nhóm ESlint, quy định trên mới chỉ bắt đầu được đề xuất từ ​​tháng 6 năm 2015. Có ý kiến ​​phản đối, ủng hộ, và cũng phải mất gần một năm (tháng 5 năm 2016), quy định này mới chính thức có hiệu lực. Team ESlint đã trải qua rất nhiều cuộc trao đổi, thậm chí phải thống nhất cái tên “no-prototype-builtins”.

Đây là một trong những nhận xét cuối cùng tôi muốn trích dẫn để chuẩn bị cho việc kết thúc bài viết này:

Toru Nagashima (mysticatea): Tôi tin rằng quy tắc này tương đối quan trọng vì kế thừa từ null là một thứ đặc biệt trong JavaScript. Tôi đoán, những người đã quen với việc lập trình bằng các ngôn ngữ khác nhưng không làm nhiều với JavaScript, sẽ khó hình dung được khả năng không tồn tại của obj.hasOwnProperty. Một số thư viện phổ biến (như chuỗi truy vấn) vẫn đang sử dụng Object.create (null).

Tóm lược

Khi mỗi đối tượng được tạo, ngoài các phương thức / thuộc tính do người dùng tạo (gọi là “OwnProperties”), còn có các phương thức / thuộc tính mà JavaScript gán cho nó (nguyên mẫu.properties). Giống như một đứa trẻ sơ sinh, mặc dù cha mẹ không dạy nó khóc – ăn – ngủ – tè – ị, nhưng bản năng của con người vẫn cho phép nó làm như vậy. Trong JavaScript vừa tạo, mỗi đối tượng có các phương thức riêng như .hasOwnProperties (), isPrototypeOf (), .vv.

Mình nghĩ bạn cần xem =>  CRM là gì? Lợi ích và tầm quan trọng của CRM với doanh nghiệp

Tuy nhiên, có những đối tượng mà người lập trình cố tình tạo ra để nó không có các phương thức / thuộc tính sẵn có ở trên (tức là không có .hasOwnProperties (), isPrototypeOf (), v.v.). Một số người gọi những đối tượng này là “sạch”, “trần trụi”,… Những đối tượng đó được tạo từ Object.create (null), không có Object.prototype.

Một khi các đối tượng đã “sạch” và có kiểu “trần trụi” ở trên, làm thế nào chúng ta có thể gọi các phương thức như .hasOwnProperties () hoặc isPrototypeOf ()? sẽ gặp lỗi ngay lập tức.

ESlint đã tạo ra một quy tắc để ngăn lập trình viên sử dụng các phương pháp đó để tránh lỗi.

Nếu bạn đã bật ESlint khi viết mã, hãy nhớ tránh sử dụng:

– Object.hasOwnProperty (),

– Object.isPrototypeOf (),

– Object.propertyIsEnumerable (),

cái nào nên sử dụng:

– Object.prototype.hasOwnProperty.call (),

– Object.prototype.isPrototypeOf.call (),

– Object.prototype.propertyIsEnumerable.call ();

Để hiểu quy tắc này có liên quan gì thì cần hiểu rất nhiều thứ cơ bản khác như Đối tượng, nguyên mẫu, phương pháp kiểm tra sự tồn tại của một số thuộc tính trong đối tượng (như sử dụng hasOwnProperties, sử dụng toán tử IN), hiểu của bản đồ,… Từ đó kiến ​​thức hổng nhiều nên hổng biết.

✤ Top 20 bài viết Tổng Hợp mới nhất :

Xem thêm nhiều Tổng Hợp mới hay

Leave A Reply

Your email address will not be published.