很多人在写一个类时会写出这样的代码:
class Person {
talk (name, msg) {
this._initName(name)
this.msg = msg
this._send()
}
_initName (name) {
this.name += ': '
}
_send () {
console.log(this.name + this.msg)
}
}
我认为更好的写法是这样:
class Person {
talk (name, msg) {
this.name = this._initName(name)
this._send(this.name, msg)
}
_initName (name) {
return name += ': '
}
_send (name, msg) {
console.log(name + msg)
}
}
在实现了同样的功能的同时,下面的代码有以下几个优点:
initName 成为了一个纯函数
纯函数的特点是没有副作用,如果在该类的其他地方仍需复用这个逻辑,可以直接使用,比如
const anotherName = this._initName(anotherName)
而原来的 initName(name) 因为和 this.name 绑定,无法很好的复用。
方法意图更加明显,可读性高
阅读代码 1 时,当看到 talk 的代码时很难看出来 this.initName(name) 和 this.send() 到底在做什么,代码 2 比代码 1 多传递了以下信息:
- this.initName 改变了 name 的值,并且这个值被赋值到了 this.name 属性
- this.send 依赖于 name 和 msg
总结为以下
- 当一个方法只修改了一个状态(实例属性)时,可以不从该方法内部去修改状态,而是返回这个修改后的值,让调用的方法去处理赋值
- 当一个方法依赖于其他状态(实例属性)时
- 如果依赖的状态较少,建议将依赖申明为参数,并从调用处传递依赖
- 如果依赖的状态特别多且复杂,传参将会变得很麻烦,但是这通常说明这个方法过于庞杂,需要先精简和拆分,再遵从上面的规则优化

