代码优化之 - pure function

2018-02-04 20:35:30 +08:00
 buzhiming

很多人在写一个类时会写出这样的代码:

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 多传递了以下信息:

总结为以下

http://buzhiming.me/2018/01/30/func-state/

2602 次点击
所在节点    编程
8 条回复
viko16
2018-02-04 21:29:47 +08:00
那为什么不直接把 _initName 和 _send 抽离出去?别的类复用的时候还少一次实例化呢
wwqgtxx
2018-02-04 22:18:59 +08:00
你这种写法在 python 下都会建议你把写法函数改成 classmethod 或者 staticmethod 了
buzhiming
2018-02-04 22:26:26 +08:00
@viko16 对,_initName 和 _send 是完全可以抽出去的,具体看情况而定吧。
buzhiming
2018-02-04 22:27:31 +08:00
@wwqgtxx 是的,js 也可以写成 static method,限于篇幅我就没讲那么细啦
doubleflower
2018-02-05 08:25:03 +08:00
你把数据都从函数里面传进去还要写个类干嘛?不伦不类,面向对象类就是用来封装数据的
buzhiming
2018-02-05 09:00:44 +08:00
@doubleflower 不对对外暴露的接口做这种优化,所有和类的使用并不冲突。
doubleflower
2018-02-05 09:54:08 +08:00
@buzhiming 这和对外暴露有什么关系。你既然实现用了类,数据就是绑在对象上的,方法是操作对象数据的,你要增加灵活性可以不从对象上取数据,还你的函数为何还要放在类里?定义一个类外的独立函数不是更好?
buzhiming
2018-02-05 12:09:13 +08:00
@doubleflower 当然有关系,数据封装在了类里面,所以在外面调用类的对外暴露的方法时,只需传必要的参数,而不要去传封装的参数,这些方法是不能优化为纯函数的。

而供类内部自己使用的私有方法,这么优化是有我说的以上的几点好处的。

你说的没错,这些函数完全可以放在类的外部作为独立函数,只不过这不是重点。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/428412

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX