Skip to content

Commit f65d0f7

Browse files
committed
docs(class): 添加 in 运算符
1 parent 9e4529a commit f65d0f7

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

docs/class.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,117 @@ FakeMath.#computeRandomNumber() // 报错
924924

925925
上面代码中,`#totallyRandomNumber`是私有属性,`#computeRandomNumber()`是私有方法,只能在`FakeMath`这个类的内部调用,外部调用就会报错。
926926

927+
### in 运算符
928+
929+
`try...catch`结构可以用来判断是否存在某个私有属性。
930+
931+
```javascript
932+
class A {
933+
use(obj) {
934+
try {
935+
obj.#foo;
936+
} catch {
937+
// 私有属性 #foo 不存在
938+
}
939+
}
940+
}
941+
942+
const a = new A();
943+
a.use(a); // 报错
944+
```
945+
946+
上面示例中,类`A`并不存在私有属性`#foo`,所以`try...catch`报错了。
947+
948+
这样的写法很麻烦,可读性很差,V8 引擎改进了`in`运算符,使它也可以用来判断私有属性。
949+
950+
```javascript
951+
class A {
952+
use(obj) {
953+
if (#foo in obj) {
954+
// 私有属性 #foo 存在
955+
} else {
956+
// 私有属性 #foo 不存在
957+
}
958+
}
959+
}
960+
```
961+
962+
上面示例中,`in`运算符判断当前类`A`的实例,是否有私有属性`#foo`,如果有返回`true`,否则返回`false`
963+
964+
`in`也可以跟`this`一起配合使用。
965+
966+
```javascript
967+
class A {
968+
#foo = 0;
969+
m() {
970+
console.log(#foo in this); // true
971+
console.log(#bar in this); // false
972+
}
973+
}
974+
```
975+
976+
注意,判断私有属性时,`in`只能用在定义该私有属性的类的内部。
977+
978+
```javascript
979+
class A {
980+
#foo = 0;
981+
static test(obj) {
982+
console.log(#foo in obj);
983+
}
984+
}
985+
986+
A.test(new A()) // true
987+
A.test({}) // false
988+
989+
class B {
990+
#foo = 0;
991+
}
992+
993+
A.test(new B()) // false
994+
```
995+
996+
上面示例中,类`A`的私有属性`#foo`,只能在类`A`内部使用`in`运算符判断,而且只对`A`的实例返回`true`,对于其他对象都返回`false`
997+
998+
子类从父类继承的私有属性,也可以使用`in`运算符来判断。
999+
1000+
```javascript
1001+
class A {
1002+
#foo = 0;
1003+
static test(obj) {
1004+
console.log(#foo in obj);
1005+
}
1006+
}
1007+
1008+
class SubA extend A {};
1009+
1010+
A.test(new SubA()) // true
1011+
```
1012+
1013+
上面示例中,`SubA`从父类继承了私有属性`#foo``in`运算符也有效。
1014+
1015+
注意,`in`运算符对于`Object.create()``Object.setPrototypeOf`形成的继承,是无效的,因为这种继承不会传递私有属性。
1016+
1017+
```javascript
1018+
class A {
1019+
#foo = 0;
1020+
static test(obj) {
1021+
console.log(#foo in obj);
1022+
}
1023+
}
1024+
const a = new A();
1025+
1026+
const o1 = Object.create(a);
1027+
A.test(o1) // false
1028+
A.test(o1.__proto__) // true
1029+
1030+
const o2 = {};
1031+
Object.setPrototypeOf(o2, A);
1032+
A.test(o2) // false
1033+
A.test(o2.__proto__) // true
1034+
```
1035+
1036+
上面示例中,对于修改原型链形成的继承,子类都取不到父类的私有属性,所以`in`运算符无效。
1037+
9271038
## new.target 属性
9281039

9291040
`new`是从构造函数生成实例对象的命令。ES6 为`new`命令引入了一个`new.target`属性,该属性一般用在构造函数之中,返回`new`命令作用于的那个构造函数。如果构造函数不是通过`new`命令或`Reflect.construct()`调用的,`new.target`会返回`undefined`,因此这个属性可以用来确定构造函数是怎么调用的。

0 commit comments

Comments
 (0)