Một sự thật thú vị về JS __proto__
![](https://post.nghiatu.com/assets/images/m/max/724/1*8ptwktzg8YTy1a3KW-j9EA.jpeg)
Nếu bạn đã theo dõi tôi đủ lâu, bạn sẽ biết __proto__
tôi luôn phản đối nhiều như thế nào, tuy nhiên, vì nó đã trở thành tiêu chuẩn ECMAScript từ lâu, nên vẫn có những trường hợp hiếm hoi tôi thấy ít nhất việc sử dụng nó để tạo nhãn hiệu cho một đối tượng có thể chấp nhận được :
const factory = (fields, {prototype} = Object) => ({
__proto__: prototype,
...fields
});
// mimic an <a /> reference
factory({href: '/'}, HTMLAnchorElement);
![](https://post.nghiatu.com/assets/images/m/max/724/1*ubXaTL0j8uwNL8T8yp1NTQ.png)
Đặt hiệu suất sang một bên và xin lưu ý rằng tôi hoàn toàn không đề xuất việc sử dụng __proto__
, bài đăng này tồn tại vì những lý do khác.
Object.prototype.__proto__
Tôi khá chắc chắn rằng mọi người đều biết trình truy cập __proto__ làm gì , vì vậy tôi muốn đề xuất cho bạn một thử thách… và vâng, đây hoàn toàn là JS hợp lệ:
class Test {}
const __proto__ = Test.prototype;
// what do these operations return?
({__proto__} instanceof Test);
({__proto__: __proto__} instanceof Test);
({"__proto__": __proto__} instanceof Test);
({["__proto__"]: __proto__} instanceof Test);
// what do these operations return?
({__proto__}.__proto__ === Test.prototype);
({__proto__: __proto__}.__proto__ === Test.prototype);
({"__proto__": __proto__}.__proto__ === Test.prototype);
({["__proto__"]: __proto__}.__proto__ === Test.prototype);
Nếu bạn chưa tự chạy những đoạn mã này để biết câu trả lời, tôi có thể giúp bạn điều đó! Trong thử thách đầu tiên, đầu ra sẽ là false
, và một lần nữa true
, và lý do là cả hai và được định nghĩa là thuộc tính riêng , trong khi phép gán thông qua cú pháp, không sử dụng các tính năng cú pháp đặc biệt, ngay cả khi có dấu ngoặc kép, thực sự chuyển qua trình truy cập.true
false
{__proto__}
{["__proto__"]}
Object.prototype.__proto__
Mặt khác, trong thử thách thứ hai (all true
), việc chúng ta truy cập __proto__
direct hay as không thực sự quan trọng ["__proto__"]
, vì vậy về cơ bản không có sự đối xứng nào trong cách chúng ta có thể kích hoạt __proto__
setter, từ cách chúng ta có thể kích hoạt __proto__
getter một lần nó hoặc là tài sản riêng hoặc là cổng thừa kế ma thuật.
… và không chỉ __proto__
Tôi chưa tự kiểm tra nhưng tôi tin rằng mọi trình truy cập __xxx__
đặc biệt kế thừa đều chịu chung một __proto__
lời nguyền, vì vậy, hãy cẩn thận khi kết hợp cú pháp JS thú vị mới nhất để gán các thuộc tính với ý định và kỳ vọng thực tế của bạn, vì mọi thứ có thể dễ dàng trở nên tồi tệ nếu bạn cố gắng hãy thông minh trong việc gán các thuộc tính này .
Và đó là tất cả mọi người!
Điều rút ra duy nhất từ bài đăng này có thể được tóm tắt như sau:
- không sử dụng các phần kế thừa chưa hoạt động của ngôn ngữ, nếu bạn muốn tránh những bất ngờ hôm nay hoặc ngày mai, về cách chúng hoạt động với cú pháp mới
- thích rõ ràng hơn (và không may là chậm hơn)
Object.setPrototypeOf
bất cứ khi nào bắt buộc phải đặt nguyên mẫu của một đối tượng theo cách thủ công, nhưng hãy sử dụng các lớp trong mọi trường hợp khác bất cứ khi nào có thể - xóa khỏi bộ nhớ của bạn bài đăng này hoặc rút gọn nó thành một câu ngắn như: “ Tôi không bao giờ nên sử dụng
__proto__
mã của mình ” và tiếp tục học những thứ mới lạ không làm rối trí não hoặc cảm xúc của bạn