Trường hợp sử dụng: # -private trường
Lời nói đầu:
Biên dịch thời gian và gian riêng tư chạy
#lĩnh vực -private cung cấp thời gian biên dịch và thời gian chạy riêng tư, mà không phải là "hack". Đó là một cơ chế để ngăn chặn truy cập vào một thành viên từ bên ngoài cơ thể lớp theo bất kỳ cách trực tiếp nào .
class A {
#a: number;
constructor(a: number) {
this.#a = a;
}
}
let foo: A = new A(42);
foo.#a; // error, not allowed outside class bodies
(foo as any).#bar; // still nope.
Kế thừa lớp an toàn
#lĩnh vực -private có được một phạm vi duy nhất. Hệ thống phân cấp lớp có thể được thực hiện mà không cần ghi đè lên các thuộc tính riêng có tên bằng nhau.
class A {
#a = "a";
fnA() { return this.#a; }
}
class B extends A {
#a = "b";
fnB() { return this.#a; }
}
const b = new B();
b.fnA(); // returns "a" ; unique property #a in A is still retained
b.fnB(); // returns "b"
Trình biên dịch TS may mắn phát ra lỗi, khi privatecác thuộc tính có nguy cơ bị ghi đè (xem ví dụ này ). Nhưng do bản chất của một tính năng thời gian biên dịch, mọi thứ vẫn có thể xảy ra vào thời gian chạy, các lỗi biên dịch đã cho được bỏ qua và / hoặc mã JS phát ra được sử dụng.
Thư viện bên ngoài
Thư viện tác giả có thể tái cấu trúc # định danh -private mà không gây ra thay đổi đột phá cho khách hàng. Người dùng thư viện ở phía bên kia được bảo vệ khỏi truy cập vào các trường nội bộ.
Bỏ qua API JS # các trường -private
Các hàm và phương thức JS tích hợp bỏ qua #các trường -private. Điều này có thể dẫn đến một lựa chọn tài sản dễ dự đoán hơn vào thời gian chạy. Ví dụ: Object.keys, Object.entries, JSON.stringify, for..invòng lặp và những người khác ( mẫu mã ; cũng thấy Matt Bierner của câu trả lời ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Các trường hợp sử dụng: privatetừ khóa
Lời nói đầu:
Truy cập vào API lớp nội bộ và trạng thái (chỉ bảo mật thời gian biên dịch)
privatecác thành viên của một lớp là các thuộc tính thông thường tại thời gian chạy. Chúng ta có thể sử dụng tính linh hoạt này để truy cập API nội bộ của lớp hoặc trạng thái từ bên ngoài. Để đáp ứng kiểm tra trình biên dịch, các cơ chế như xác nhận kiểu, truy cập thuộc tính động hoặc @ts-ignorecó thể được sử dụng giữa các trình khác.
Ví dụ với xác nhận kiểu ( as/ <>) và anygán biến được gõ:
class A {
constructor(private a: number) { }
}
const a = new A(10);
a.a; // TS compile error
(a as any).a; // works
const casted: any = a; casted.a // works
TS thậm chí còn cho phép truy cập thuộc tính động của một privatethành viên với một lối thoát :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Truy cập cá nhân có thể có ý nghĩa ở đâu? (1) kiểm tra đơn vị, (2) gỡ lỗi / ghi nhật ký hoặc (3) các tình huống nâng cao khác với các lớp bên trong dự án (danh sách kết thúc mở).
Truy cập vào các biến nội bộ là một chút mâu thuẫn - nếu không, bạn sẽ không thực hiện chúng privateở vị trí đầu tiên. Để đưa ra một ví dụ, các bài kiểm tra đơn vị được cho là các hộp đen / xám với các trường riêng được ẩn làm chi tiết triển khai. Trong thực tế, có thể có các cách tiếp cận hợp lệ từ trường hợp này sang trường hợp khác.
Có sẵn trong mọi môi trường ES
Công cụ privatesửa đổi TS có thể được sử dụng với tất cả các mục tiêu ES. #lĩnh vực -private chỉ có sẵn cho target ES2015/ ES6hoặc cao hơn. Trong ES6 +, WeakMapđược sử dụng nội bộ như triển khai downlevel (xem tại đây ). Các #lĩnh vực bí mật bản địa hiện đang yêu cầutarget esnext .
Tính nhất quán và tương thích
Các nhóm có thể sử dụng các nguyên tắc mã hóa và quy tắc kẻ nói dối để thực thi việc sử dụng privatenhư là công cụ sửa đổi truy cập duy nhất. Hạn chế này có thể giúp thống nhất và tránh nhầm lẫn với #ký hiệu trường -private theo cách tương thích ngược.
Nếu được yêu cầu, các thuộc tính tham số (tốc ký gán của hàm tạo) là một nút chặn hiển thị. Chúng chỉ có thể được sử dụng với privatetừ khóa và chưa có kế hoạch triển khai chúng cho #các lĩnh vực -private.
Những lý do khác
privatecó thể cung cấp hiệu suất thời gian chạy tốt hơn trong một số trường hợp xuống cấp (xem tại đây ).
- Cho đến nay không có phương pháp lớp học riêng cứng nào có sẵn trong TS.
- Một số người thích
privateký hiệu từ khóa tốt hơn 😊.
Lưu ý cả hai
Cả hai cách tiếp cận đều tạo ra một số loại danh nghĩa hoặc nhãn hiệu tại thời điểm biên dịch.
class A1 { private a = 0; }
class A2 { private a = 42; }
const a: A1 = new A2();
// error: "separate declarations of a private property 'a'"
// same with hard private fields
Ngoài ra, cả hai đều cho phép truy cập thể hiện chéo: một thể hiện của lớp Acó thể truy cập các thành viên riêng của các Athể hiện khác :
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
Nguồn