public field 和private field组成了class field,这篇文章不讲private field ,只谈public field所带来的问题
我会根据例子来讲解,这样会更好理解一些
class SafeUser {
constructor() {
this.password = '1234'
}
}
上面代码非常简单,就是声明了一个SafeUser类,接下来我们根据public field来简化一下代码
class SafeUser {
password = '123'
}
这两种方式有什么区别呢?
下面这种方式在执行的时候调用了
Object.defineProperty
为当前的实例添加属性,当然上面那种写法也是在当前实例上添加password属性
在一般的情况下,这两种写法是没什么差别的,但在一些特殊的情况下,下面的写法会出现问题。举个例子
class User {
get password() {
return this._password
}
set password(val) {
this._password = val;
console.log('change password')
}
}
class SafeUser extends User {
constructor() {
super()
this.password = '1234'
}
}
父类 User,子类SafeUser,我们的目的在于当SafeUser的实例每次改变时,都打印出change password,(在真实的开发中,可能是以日志的形式记录下来)
看下效果
我们发现当改变password的时候,确实会打印出'change password'
不仅如此,在生成一个实例的时候,就已经打印出来'change password',这是因为调用super,初始化了父类,
接下来this.password = ‘1234’,触发了set函数,也就是触发了父类的set方法,为当前实例添加了_password属性
所以password不是inst的属性,是它从原型上找的,_password才是inst自身的属性,下图就验证了我们的说法
如果把SafeUser改为下面那种public field的写法,就会出现问题
class User {
get password() {
return this._password
}
set password(val) {
this._password = val;
console.log('change password')
}
}
class SafeUser extends User{
password = '123'
}
具体的差别,我们从下面的截图就可以看出来
改变password没有触发set函数
为什么会这样呢?
就向上面说的,内部相当于执行了
Object.defineProperty
既然inst自己有password属性,就不会访问父级的password了