ใช้กรณี: - #
เขตข้อมูลส่วนบุคคล
คำนำ:
ความเป็นส่วนตัวรวบรวมและเวลาทำงาน
#
- เขตข้อมูลส่วนบุคคลให้ความเป็นส่วนตัวเวลารวบรวมและเวลาทำงานซึ่งไม่ใช่ "แฮ็ก" มันเป็นกลไกในการป้องกันการเข้าถึงสมาชิกออกจากนอกร่างกายชั้นเรียนในทางใด ๆ โดยตรง
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.
การสืบทอดคลาสที่ปลอดภัย
#
เขตข้อมูลส่วนตัวได้รับขอบเขตที่ไม่ซ้ำกัน ลำดับชั้นของคลาสสามารถนำไปใช้ได้โดยไม่ต้องเขียนทับคุณสมบัติส่วนตัวด้วยชื่อที่เท่าเทียมกันโดยไม่ได้ตั้งใจ
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"
ผู้แปล TS โชคดีที่ปล่อยข้อผิดพลาดเมื่อprivate
คุณสมบัติอยู่ในอันตรายที่จะถูกเขียนทับ (ดูตัวอย่างนี้ ) แต่เนื่องจากลักษณะของการรวบรวมเวลาคุณสมบัติทุกอย่างยังคงเป็นไปได้ที่เวลาทำงานข้อผิดพลาดการรวบรวมที่กำหนดจะถูกละเว้นและ / หรือปล่อยรหัส JS ใช้
ห้องสมุดภายนอก
ผู้เขียนไลบรารีสามารถ refactor #
-private identifier โดยไม่ทำให้การเปลี่ยนแปลงที่เกิดขึ้นกับลูกค้า ผู้ใช้ห้องสมุดในอีกด้านหนึ่งได้รับการปกป้องจากการเข้าถึงฟิลด์ภายใน
JS API ละเว้น#
ช่อง -private
ฟังก์ชั่น JS ในตัวและเมธอดละเว้น#
ฟิลด์ -private ซึ่งอาจส่งผลให้การเลือกคุณสมบัติที่คาดการณ์ได้มากขึ้นในขณะใช้งาน ตัวอย่าง: Object.keys
, Object.entries
, JSON.stringify
, for..in
ห่วงและอื่น ๆ ( ตัวอย่างรหัสดูยังแมตต์ Bierner ของคำตอบ ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
ใช้กรณี: private
คำหลัก
คำนำ:
การเข้าถึง API คลาสภายในและสถานะ (ความเป็นส่วนตัวเวลารวบรวมเท่านั้น)
private
สมาชิกของคลาสเป็นคุณสมบัติทั่วไป ณ รันไทม์ เราสามารถใช้ความยืดหยุ่นนี้เพื่อเข้าถึง API ภายในหรือสถานะของคลาสจากภายนอก เพื่อตอบสนองการตรวจสอบคอมไพเลอร์กลไกเช่นประเภทยืนยันการเข้าถึงสถานที่ให้บริการแบบไดนามิกหรือ@ts-ignore
อาจจะใช้ในหมู่คนอื่น ๆ
ตัวอย่างที่มีการยืนยันประเภท ( as
/ <>
) และการany
กำหนดตัวแปรที่พิมพ์:
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 อนุญาตให้เข้าถึงคุณสมบัติแบบไดนามิกของprivate
สมาชิกด้วยescape-hatch :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
การเข้าถึงแบบส่วนตัวสามารถทำให้รู้สึกได้ที่ไหน (1) การทดสอบหน่วย (2) สถานการณ์การดีบัก / การบันทึกหรือ (3) สถานการณ์กรณีขั้นสูงอื่น ๆ ที่มีคลาสโครงการภายใน (รายการปลายเปิด)
การเข้าถึงตัวแปรภายในเป็นสิ่งที่ขัดแย้งกันไม่เช่นนั้นคุณจะไม่ทำให้มัน private
เป็นที่แรก เพื่อให้เป็นตัวอย่างการทดสอบหน่วยควรจะเป็นกล่องดำ / เทาที่มีช่องส่วนตัวซ่อนอยู่ตามรายละเอียดการใช้งาน แม้ว่าในทางปฏิบัติอาจมีวิธีการที่ถูกต้องในแต่ละกรณี
พร้อมใช้งานในสภาพแวดล้อม ES ทั้งหมด
private
ตัวดัดแปลงTS สามารถใช้กับเป้าหมาย ES ทั้งหมดได้ #
- เขตข้อมูลส่วนบุคคลใช้ได้เฉพาะสำหรับtarget
ES2015
/ ES6
หรือสูงกว่า ใน ES6 + WeakMap
จะใช้เป็นการดำเนินการระดับล่าง(ดูที่นี่ ) พื้นเมืองเขตข้อมูลส่วนตัวในปัจจุบันจำเป็นต้องมี#
target
esnext
ความสอดคล้องและความเข้ากันได้
ทีมงานอาจใช้แนวทางการเข้ารหัสและกฎ linter เพื่อบังคับให้ใช้private
เป็นตัวดัดแปลงการเข้าถึงเท่านั้น ข้อ จำกัด นี้สามารถช่วยในเรื่องความสอดคล้องและหลีกเลี่ยงความสับสนกับ#
สัญลักษณ์ข้อมูลส่วนบุคคลในลักษณะที่เข้ากันได้ย้อนหลัง
หากจำเป็นต้องใช้คุณสมบัติของพารามิเตอร์ (ชวเลขการกำหนดตัวสร้าง) เป็นตัวหยุดการแสดง สามารถใช้ได้กับprivate
คำหลักเท่านั้นและยังไม่มีแผนในการนำไปใช้กับ#
ฟิลด์ -private
เหตุผลอื่น ๆ
private
อาจให้ประสิทธิภาพการใช้งานดีขึ้นในบางกรณีที่มีการปรับระดับ (ดูที่นี่ )
- ไม่มีวิธีการเรียนแบบส่วนตัวที่ยากใน TS จนถึงปัจจุบัน
- บางคนชอบ
private
สัญกรณ์คำหลักดีกว่า😊
หมายเหตุทั้งสอง
ทั้งสองวิธีสร้างประเภทที่ระบุหรือตราสินค้าบางประเภทในเวลารวบรวม
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
นอกจากนี้ทั้งสองอนุญาตการเข้าถึงข้ามอินสแตนซ์: อินสแตนซ์ของคลาสA
สามารถเข้าถึงสมาชิกส่วนตัวของA
อินสแตนซ์อื่น:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
แหล่งที่มา