一、写在前面
第一天
写在前面,先看几段代码,用你的大脑编译运行一下试试? No errors, no warnings
!
ts
const config = new Config()
config.version = '1.0.0'
console.log(config.version)
乍一看,这代码会打印 1.0.0
,于是跑一下试试?
王德发?!! 于是打开
Config
类看看,好家伙
ts
export class Config {
private _version!: string
public get version(): string {
return this._version
}
public set version(value: string) {
this._version = '莫挨劳资'
}
}
原来是 getter/setter
啊!这玩意我熟!原来 config.version = '1.0.0'
不是给 Config 的 version 字段赋值,而是调用了一个 version 的 set 方法。
这点我可是很不喜欢的,这已经让人产生了心智负担,赋值、方法调用傻傻分不清楚,还得看了实现才知道。
第二天
你再问我上面的问题,我可不敢拍着胸脯说答案了。
于是第二个问题又来了
ts
const user = new User()
user.name = '彭于晏'
user.age = 33
user.length = '15cm'
console.log(JSON.stringify(user))
凭我三十余年生活经验,这不是在序列化JSON到字符串吗?分分钟在脑海里编译运行,肯定输出这个啊:
json
{"name":"彭于晏","age":33,"length":"15cm"}
因为昨天上当了,今天还是验证跑一下看看结果:
额,这是什么时候走漏的风声?
表示不服,再一次打开 User 类看看究竟,不看不知道,一看好家伙~
ts
export class User {
/**
* # 昵称
*/
private nickname!: string
public get name(): string {
return this.nickname
}
public set name(value: string) {
this.nickname = 'Hamm'
}
/**
* # 年龄
*/
private year!: number
public get age(): number {
return this.year
}
public set age(value: number) {
this.year = 22
}
/**
* # 长度
*/
private len!: string
public get length(): string {
return this.len
}
public set length(value: string) {
this.len = `${parseInt(value.replace('cm', '')) + 3}cm`
}
}
这谁干的!干得漂亮!!!
以上剧情纯属事实,如有雷同,你也很棒!
二、我不太喜欢Getter和Setter
1. vscode自动重构的属性名带下划线
vscode 提供了属性一键自动生成 getter/setter
,为了保持属性名和方法名不重复,于是会自动生成一个属性名前面加下划线的新属性,然后将原属性干掉并生成 get
set
两个方法。
生成的最终结果如下图
虽然在生成过程中可以新起一个自定义属性名,但我真的很烦,如果使用默认,我的 eslint 规则又会认为 属性名不符合规范。。。
2. 调用方的心智负担
如下面之前贴过的代码:
ts
const config = new Config()
config.version = '1.0.0'
console.log(config.version)
在不阅读 Config 类的情况下,会主观认为 config.version = "1.0.0"
是在给 属性赋值 ,而调用 let version = config.version
会认为是将刚才赋的值取出来使用。
3. Get/Set方法和普通方法区别对待
在有 private
protected
public
等访问修饰符的情况下,类本身有 属性 、方法 、构造 就已经足够满足需求了,这里非得上一个 get set 连写法都要区别对待的特殊方法形式,构造方法 constructor
表示第一个不服,劳资都没特殊对待,凭什么它俩要特殊对待?
4. 我理解的属性
属性应该是一个类上最基础的最终数据存储,设置到属性上的值是什么,那取出来的值也一定得是什么:
老张,我这瓶水放你这,一会我来拿。
这里我其实是调用了老张的一个赋值。所以一会回来拿到的水,还是那瓶水:
ts
const store = new Store()
store.water = "哇哈哈"
// a few moments later
console.log(store.water) // 哇哈哈
所以,上面的输出一定得是 哇哈哈 才合理, 第一天碰到的问题,就不应该存在。
5. 我理解的方法
方法应该是一个类上的 委托事项流程 的整合体,不管是普通方法,还是get/set
,甚至是 构造方法
。
只是构造方法比较特殊,也应该是整个类中唯一的特殊。
get
/ set
方法都应该只是从规范上形成的一些约定俗成的方法,而且既然是方法,get
/ set
的调用都应该加上 括号 (),才会便于理解。而且方法名和属性名也没有一定不重复的限定。
三、Getter/Setter的优势
简单说一些吧。
1. 数据拦截
利用 get set 方法来做数据拦截,这个点这篇文章中不过多讲,可以参考一些前端框架的双向数据绑定实现来学习。
2. 数据转换
在前后端数据转换时,除了我们之前使用的 # 基于装饰器-我是这么处理TypeScript项目数据转换的 之外,使用 get
set
来做数据转换可能也会是一个很棒的方式(当然,属性名 和 get/set
不能重复的问题,还可以再思考思考)。
3. 其他优势
关我屁事。
四、写在最后
这是今天突然群里的小伙伴发起的一个问题,突然想到这么多,那就记下来。
每日一水,每天一桶。
That's all, 就酱。