@@ -924,6 +924,117 @@ FakeMath.#computeRandomNumber() // 报错
924
924
925
925
上面代码中,` #totallyRandomNumber ` 是私有属性,` #computeRandomNumber() ` 是私有方法,只能在` FakeMath ` 这个类的内部调用,外部调用就会报错。
926
926
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
+
927
1038
## new.target 属性
928
1039
929
1040
` new ` 是从构造函数生成实例对象的命令。ES6 为` new ` 命令引入了一个` new.target ` 属性,该属性一般用在构造函数之中,返回` new ` 命令作用于的那个构造函数。如果构造函数不是通过` new ` 命令或` Reflect.construct() ` 调用的,` new.target ` 会返回` undefined ` ,因此这个属性可以用来确定构造函数是怎么调用的。
0 commit comments