ES 编码实践 —— 链式调用
published
链式调用的形式
obj.m1().m2().m3()....mN()
链式调用的优缺点
-
优点
- 减少了代码量,降低了冗余度
-
缺点
- 占用了函数的返回值
实现方法
方法 1:实例方法返回对象自身 —— 返回 this
class Counter {
constructor (num) {
this.number = num
}
add (num) {
this.number += num
return this
}
minus (num) {
this.number -= num
return this
}
show () {
console.log(this.number)
return this
}
}
const i = new Counter(10)
i.add(5).add(5).minus(2).show().minus(2).show()
这种方法的缺点:每定义一个类,其方法体中都要返回 this
。 如果是已经写好的类,打算要让它支持链式调用,怎么办?批量修改原型方法。但是,手动来做很繁琐。写些辅助函数来自动完成这个事儿吧:
class Counter {
constructor (num) {
this.number = num
}
add (num) {
this.number += num
}
minus (num) {
this.number -= num
}
show () {
console.log(this.number)
}
}
// add `return this` for method
function addThis (class_, method, fn) {
class_.prototype[method] = function (...args) {
fn.apply(this, [...args])
return this
}
}
// add `return this` for multiple methods
for (let m of ['add', 'minus', 'show']) {
addThis(Counter, m, Counter.prototype[m])
}
const i = new Counter(10)
i.add(5).add(5).minus(2).show().minus(2).show()
方法 2:利用函数代理对象
class Counter {
constructor (num) {
this.number = num
}
add (num) {
this.number += num
}
minus (num) {
this.number -= num
}
show () {
console.log(this.number)
}
}
function chain (obj) {
function f (method, ...args) {
if (arguments.length === 0) {
return obj
}
obj[method](...args)
return f
}
return f
}
const i = new Counter(10)
chain(i)('add', 5)('add', 5)('minus', 2)('show')('minus', 2)('show')
这种方式用了闭包,比较费内存,如果没什么必要,还是用别的方法。