ç§æå
ç´ æ¯å¸¸è§çç±»çå
¬æå±æ§ï¼å
æ¬ç±»å段ãç±»æ¹æ³çï¼ç对åºãç§æå
ç´ éè¿æ·»å #
åç¼æ¥å建ï¼å¨ç±»çå¤é¨æ æ³åæ³å°å¼ç¨ãè¿äºç±»å±æ§çç§æå°è£
ç± JavaScript æ¬èº«å¼ºå¶æ§è¡ã
å¨è¿ç§è¯æ³åºç°ä¹åï¼JavaScript è¯è¨æ¬èº«å¹¶æ²¡æåçæ¯æç§æå
ç´ ãå¨ååç»§æ¿ä¸ï¼å¯ä»¥éè¿ä½¿ç¨ WeakMap
对象æè
éå
çæ¹å¼æ¥æ¨¡æç§æå
ç´ çè¡ä¸ºï¼ä½å°±æç¨æ§èè¨ï¼å®ä»¬æ æ³ä¸ #
è¯æ³ç¸æå¹¶è®ºã
夿³¨ï¼ å¨ MDN ä¸ï¼æä»¬é¿å
ä½¿ç¨æ¯è¯âç§æå±æ§âãJavaScript ä¸ç屿§ä»¥å符串æç¬¦å·ä¸ºé®ï¼ä¸å
·æ writable
ãenumerable
å configurable
çç¹æ§ï¼attributeï¼ï¼èç§æå
ç´ åä¸å
·æè¿äºç¹æ§ãè½ç¶ç§æå
ç´ ä½¿ç¨çæçç¹è¡¨ç¤ºæ³æ¥è®¿é®ï¼ä½å®ä»¬ä¸è½è¢«ä»£çãæä¸¾ãå é¤æä½¿ç¨ä»»ä½ Object
æ¹æ³è¿è¡äº¤äºã
class ClassWithPrivate {
#privateField;
#privateFieldWithInitializer = 42;
#privateMethod() {
// â¦
}
static #privateStaticField;
static #privateStaticFieldWithInitializer = 42;
static #privateStaticMethod() {
// â¦
}
}
è¿æä¸äºé¢å¤çè¯æ³éå¶ï¼
#constructor
ã大夿°ç±»å ç´ é½æå ¶å¯¹åºçç§æé¡¹ï¼
è¿äºç¹æ§ç»ç§°ä¸ºç§æå ç´ ãç¶èï¼JavaScript 䏿é 彿°ä¸è½æ¯ç§æçã为äºé²æ¢å¨ç±»ä¹å¤æé ç±»ï¼ä½ å¿ é¡»ä½¿ç¨ç§ææ å¿ã
ç§æå
ç´ éè¿â#åç§°âï¼â#â读ä½âhashâï¼æ¥å£°æï¼å®ä»¬æ¯ä»¥ #
åç¼å¼å¤´çæ è¯ç¬¦ãè¿ä¸ª #
åç¼æ¯å±æ§åç§°çåºæé¨åï¼ä½ å¯ä»¥å°å
¶ä¸æ§çä¸å线åç¼çº¦å® _privateField
è¿è¡ç±»æ¯ï¼ä½å®ä¸æ¯æ®éçåç¬¦ä¸²å±æ§ï¼å æ¤æ æ³ä½¿ç¨æ¹æ¬å·è¡¨ç¤ºæ³å¨æè®¿é®å®ã
å¨ç±»å¤é¨å¼ç¨ #
åç§°ãå¼ç¨æªå¨ç±»å
é¨å£°æçç§æå
ç´ ï¼æå°è¯ä½¿ç¨ delete
ç§»é¤å£°æçå
ç´ é½ä¼æåºè¯æ³é误ã
class ClassWithPrivateField {
#privateField;
constructor() {;
delete this.#privateField; // Syntax error
this.#undeclaredField = 42; // Syntax error
}
}
const instance = new ClassWithPrivateField();
instance.#privateField; // Syntax error
JavaScript ä½ä¸ºå¨æè¯è¨ï¼è½å¤å¨ç¼è¯æ¶æ£æ¥ #
æ è¯ç¬¦çè¯æ³ï¼ä½¿å
¶ä¸æ®é屿§çè¯æ³ä¸åã
夿³¨ï¼ Chrome æ§å¶å°ä¸è¿è¡ç代ç å¯ä»¥è®¿é®ç±»çç§æå ç´ ãè¿æ¯ JavaScript è¯æ³éå¶å¯¹å¼åè å·¥å ·çä¸ç§æ¾å®½ã
å¦æä½ è®¿é®å¯¹è±¡ä¸ä¸åå¨çç§æå
ç´ ï¼ä¼æåº TypeError
é误ï¼è䏿¯åæ®é屿§ä¸æ ·è¿å undefined
ã
class C {
#x;
static getX(obj) {
return obj.#x;
}
}
console.log(C.getX(new C())); // undefined
console.log(C.getX({})); // TypeError: Cannot read private member #x from an object whose class did not declare it
è¿ä¸ªç¤ºä¾ä¹æ¼ç¤ºäºä½ å¯ä»¥å¨éæå½æ°ä¸ä»¥åå¨å¤é¨å®ä¹çç±»çå®ä¾ä¸è®¿é®ç§æå ç´ ã
ä½ ä¹å¯ä»¥ä½¿ç¨ in
è¿ç®ç¬¦æ¥æ£æ¥ä¸ä¸ªå¤é¨å®ä¹ç对象æ¯å¦æ¥æä¸ä¸ªç§æå
ç´ ã妿坹åºçç§æåæ®µæç§ææ¹æ³åå¨ï¼åè¿å true
ï¼å¦åè¿å false
ã
class C {
#x;
constructor(x) {
this.#x = x;
}
static getX(obj) {
if (#x in obj) return obj.#x;
return "obj å¿
é¡»æ¯ C çå®ä¾";
}
}
console.log(C.getX(new C("foo"))); // "foo"
console.log(C.getX(new C(0.196))); // 0.196
console.log(C.getX(new C(new Date()))); // å½åçæ¥æåæ¶é´
console.log(C.getX({})); // "obj å¿
é¡»æ¯ C çå®ä¾"
请注æï¼ç§æåç§°å§ç»éè¦æå声æå¹¶ä¸ä¸å¯å é¤ï¼å¦æä½ åç°ä¸ä¸ªå¯¹è±¡å
·æå½åç±»çä¸ä¸ªç§æå
ç´ ï¼æ 论æ¯éè¿ try...catch
è¿æ¯ in
æ£æ¥ï¼ï¼é£ä¹å®ä¸å®å
·æå
¶ä»ææçç§æå
ç´ ãé常æ
åµä¸ï¼ä¸ä¸ªå¯¹è±¡å
·æä¸ä¸ªç±»çç§æå
ç´ æå³ç宿¯ç±è¯¥ç±»æé çï¼å°½ç®¡å¹¶éæ»æ¯å¦æ¤ï¼ã
ç§æå
ç´ ä¸æ¯ååç»§æ¿æ¨¡åçä¸é¨åï¼å 为å®ä»¬åªè½å¨å½åç±»å
é¨è¢«è®¿é®ï¼èä¸ä¸è½è¢«å类继æ¿ãä¸åç±»çç§æå
ç´ åç§°ä¹é´æ²¡æä»»ä½äº¤äºãå®ä»¬æ¯éå 卿¯ä¸ªå®ä¾ä¸çå¤é¨å
æ°æ®ï¼ç±ç±»æ¬èº«ç®¡çãå æ¤ï¼Object.freeze()
å Object.seal()
å¯¹ç§æå
ç´ æ²¡æå½±åã
å ³äºå¦ä½ä»¥å使¶åå§åç§æåæ®µçæ´å¤ä¿¡æ¯ï¼è¯·åé å ¬æç±»å段ã
ç¤ºä¾ ç§æåæ®µç§æåæ®µå æ¬ç§æå®ä¾å段åç§æéæå段ãç§æåæ®µåªè½å¨ç±»å£°æå é¨è¢«è®¿é®ã
ç§æå®ä¾å段类似äºå¯¹åºçå ¬æå段ï¼ç§æå®ä¾å段ï¼
super()
ä¹åç«å³æ·»å ï¼å¹¶ä¸class ClassWithPrivateField {
#privateField;
constructor() {
this.#privateField = 42;
}
}
class Subclass extends ClassWithPrivateField {
#subPrivateField;
constructor() {
super();
this.#subPrivateField = 23;
}
}
new Subclass(); // å¨ä¸äºå¼åå·¥å
·ä¸ä¼æ¾ç¤ºï¼Subclass {#privateField: 42, #subPrivateField: 23}
夿³¨ï¼ ClassWithPrivateField
åºç±»ç #privateField
æ¯ ClassWithPrivateField
ç§æçï¼ä¸è½ä»æ´¾çç Subclass
ç±»ä¸è®¿é®ã
ç±»çæé 彿°å¯ä»¥è¿åä¸ä¸ªä¸åç对象ï¼è¿ä¸ªå¯¹è±¡å°è¢«ç¨ä½æ´¾çç±»çæé 彿°ç this
ãæ´¾çç±»å¯ä»¥å¨è¿ä¸ªè¿åç对象ä¸å®ä¹ç§æå段ââè¿æå³çå¯ä»¥å°ç§æå段âéå âå°ä¸ç¸å
³ç对象ä¸ã
class Stamper extends class {
// åºç±»ï¼å
¶æé 彿°è¿åç»å®ç对象
constructor(obj) {
return obj;
}
} {
// è¿ä¸ªå£°æä¼å°ç§æå段âéå âå°åºç±»æé 彿°è¿åç对象ä¸
#stamp = 42;
static getStamp(obj) {
return obj.#stamp;
}
}
const obj = {};
new Stamper(obj);
// `Stamper` è°ç¨è¿å `obj` ç `Base`ï¼æä»¥ `obj` ç°å¨æ¯ `this` å¼ãç¶å `Stamper` å¨ `obj` ä¸å®ä¹ `#stamp`
console.log(obj); // å¨ä¸äºå¼åå·¥å
·ä¸ä¼æ¾ç¤ºï¼{#stamp: 42}
console.log(Stamper.getStamp(obj)); // 42
console.log(obj instanceof Stamper); // false
// ä½ æ æ³å°ç§æå
ç´ éå å°åä¸ä¸ªå¯¹è±¡ä¸¤æ¬¡
new Stamper(obj); // Error: Initializing an object twice is an error with private fields
è¦åï¼ è¿å¯è½æ¯ä¸ç§éå¸¸ä»¤äººå°æçåæ³ãä½ åºè¯¥é¿å
仿é 彿°è¿åä»»ä½ä¸è¥¿ââå°¤å
¶æ¯ä¸ this
æ å
³çä¸è¥¿ã
类似äºå ¬æéæå段ï¼ç§æéæå段ï¼
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
return ClassWithPrivateStaticField.#privateStaticField;
}
}
console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42
ç§æéæå段æä¸äºéå¶ï¼åªæå®ä¹ç§æéæå段çç±»æè½è®¿é®è¯¥å段ãè¿å¯è½å¯¼è´ä½¿ç¨ this
æ¶åºç°ææ³ä¸å°çè¡ä¸ºãå¨ä¸é¢çä¾åä¸ï¼this
æå Subclass
ç±»ï¼è䏿¯ ClassWithPrivateStaticField
ç±»ï¼ï¼å¯¼è´å°è¯è°ç¨ Subclass.publicStaticMethod()
æ¶æåº TypeError
ã
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
return this.#privateStaticField;
}
}
class Subclass extends ClassWithPrivateStaticField {}
Subclass.publicStaticMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
å¦æä½ ä½¿ç¨ super
æ¥è°ç¨è¯¥æ¹æ³ï¼ä¹æ¯å¦æ¤ï¼å 为 super
æ¹æ³è¢«è°ç¨æ¶ä¸ä¼å°åºç±»ä½ä¸º this
å¼ã
class ClassWithPrivateStaticField {
static #privateStaticField = 42;
static publicStaticMethod() {
// å½éè¿ super è°ç¨æ¶ï¼`this` ä»ç¶æå Subclass
return this.#privateStaticField;
}
}
class Subclass extends ClassWithPrivateStaticField {
static callSuperMethod() {
return super.publicStaticMethod();
}
}
Subclass.callSuperMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
å»ºè®®ä½ å§ç»éè¿ç±»åæ¥è®¿é®ç§æéæå段ï¼è䏿¯éè¿ this
ï¼ä»¥é¿å
ç»§æ¿ç ´åæ¹æ³ã
ç§ææ¹æ³å æ¬ç§æå®ä¾æ¹æ³åç§æéææ¹æ³ãç§ææ¹æ³åªè½å¨ç±»å£°æå é¨è¢«è®¿é®ã
ç§æå®ä¾æ¹æ³ä¸å ¬æå®ä¾æ¹æ³ä¸åï¼ç§æå®ä¾æ¹æ³ï¼
.prototype
屿§ä¸è®¿é®ãclass ClassWithPrivateMethod {
#privateMethod() {
return 42;
}
publicMethod() {
return this.#privateMethod();
}
}
const instance = new ClassWithPrivateMethod();
console.log(instance.publicMethod()); // 42
ç§æå®ä¾æ¹æ³å¯ä»¥æ¯çæå¨æ¹æ³ã弿¥æ¹æ³æå¼æ¥çæå¨æ¹æ³ãç§æ getter å setter æ¹æ³ä¹åæ ·éç¨ï¼å¹¶ä¸ä¸å ¬æ getter å setter æ¹æ³çè¯æ³ç¸åã
class ClassWithPrivateAccessor {
#message;
get #decoratedMessage() {
return `ð¬${this.#message}ð`;
}
set #decoratedMessage(msg) {
this.#message = msg;
}
constructor() {
this.#decoratedMessage = "hello world";
console.log(this.#decoratedMessage);
}
}
new ClassWithPrivateAccessor(); // ð¬hello worldð
ä¸å
¬ææ¹æ³ä¸åï¼ç§ææ¹æ³ä¸è½å¨ç±»ç .prototype
屿§ä¸è®¿é®ã
class C {
#method() {}
static getMethod(x) {
return x.#method;
}
}
console.log(C.getMethod(new C())); // [Function: #method]
console.log(C.getMethod(C.prototype)); // TypeError: Receiver must be an instance of class C
ç§æéææ¹æ³
ä¸å ¬æéææ¹æ³ç±»ä¼¼ï¼ç§æéææ¹æ³ï¼
class ClassWithPrivateStaticMethod {
static #privateStaticMethod() {
return 42;
}
static publicStaticMethod() {
return ClassWithPrivateStaticMethod.#privateStaticMethod();
}
}
console.log(ClassWithPrivateStaticMethod.publicStaticMethod()); // 42
ç§æéææ¹æ³å¯ä»¥æ¯çæå¨æ¹æ³ï¼å¼æ¥æ¹æ³æå¼æ¥çæå¨æ¹æ³ã
å颿å°çç§æéæå段çéå¶åæ ·éç¨äºç§æéææ¹æ³ãåæ ·å°ï¼ä½¿ç¨ this
å¯è½ä¼åºç°ææ³ä¸å°çè¡ä¸ºãå¨ä¸é¢çä¾åä¸ï¼å½æä»¬å°è¯è°ç¨ Subclass.publicStaticMethod()
æ¶ï¼this
æå Subclass
ç±»ï¼è䏿¯ ClassWithPrivateStaticMethod
ç±»ï¼ï¼å¯¼è´æåº TypeError
ã
class ClassWithPrivateStaticMethod {
static #privateStaticMethod() {
return 42;
}
static publicStaticMethod() {
return this.#privateStaticMethod();
}
}
class Subclass extends ClassWithPrivateStaticMethod {}
console.log(Subclass.publicStaticMethod()); // TypeError: Cannot read private member #privateStaticMethod from an object whose class did not declare it
模æç§ææé 彿°
许å¤å ¶ä»è¯è¨é½æä¾äºå°æé 彿°æ è®°ä¸ºç§æçè½åï¼è¿å°é»æ¢ç±»å¨ç±»å é¨å¤è¢«å®ä¾åââåªè½ä½¿ç¨å建å®ä¾çéæå·¥åæ¹æ³ï¼æè æ ¹æ¬ä¸è½å建å®ä¾ãJavaScript 没æåççç§ææé 彿°çè¯æ³ï¼ä½å¯ä»¥éè¿ç§æéææ å¿æ¥å®ç°ã
class PrivateConstructor {
static #isInternalConstructing = false;
constructor() {
if (!PrivateConstructor.#isInternalConstructing) {
throw new TypeError("PrivateConstructor is not constructable");
}
PrivateConstructor.#isInternalConstructing = false;
// æ·»å æ´å¤çåå§åé»è¾
}
static create() {
PrivateConstructor.#isInternalConstructing = true;
const instance = new PrivateConstructor();
return instance;
}
}
new PrivateConstructor(); // TypeError: PrivateConstructor is not constructable
PrivateConstructor.create(); // PrivateConstructor {}
è§è æµè§å¨å
¼å®¹æ§ javascript.classes.private_class_fields javascript.classes.private_class_fields_in javascript.classes.private_class_methods åè§
class
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4