在社会中,评价一个人的能力与价值时,常常会出现两种不同的标准:一种是“凭关系”,另一种是“凭能力”。这两种标准在不同的文化、行业和个人价值观中都有所体现,它们各自有其支持者和批评者。
在编程语言里面,也有这样的两种标准,分别以不同的方式把代码组织起来,将数据结构与函数联系起来。本文将简单探讨这两个常见标准的应用和作用原理。
class 模型
在 Javascript 语言中,提供了 class 关键字,我们可以使用它来定义类。重要的是,类是可以扩展的,在实例上调用方法时,会按照原型链的顺序去查找方法定义。例如:
class Animal {
move() { return 'move' }
}
class Monkey extends Animal {
jump() { return 'jump' }
}
class Human extends Monkey {
write() { return 'write' }
}
extends 关键字可以帮助我们定义一个基于其它类扩展而来的新类。我们可以这样获取到原型链:
let me = new Human()
let proto = me.__proto__
let r = []
while (proto !== null) {
r.push(proto.constructor.name)
proto = proto.__proto__
}
我们会得到 r 是这样的:['Human', 'Monkey', 'Animal', 'Object']。当我们调用方法的时候,方法调用的成功与否取决于原型链上是否有对应的定义。比如调用 me.move(),它在Animal 类里有定义,于是调用成功。
这是 class 模型,我愿意将其称为是“凭关系”进行调用的模型,只要在实例本身的类,或者父母类,祖父母类等等里面有定义,即可调用。
基于能力的模型
相比于基于关系的模型,基于能力的模型要显得简单许多。只要实例满足某种特质,对应的方法就可以作用于这个实例上,而不需要考虑这个实例的关系如何。
let me = {
moveable: true,
freezable: false
}
function move(x) { return x.moveable ? 'move' : undefined }
function freeze(x) { return x.freezable ? 'freeze' : undefined }
在这种模型里,数据和方法是相互独立的。它的好处是简洁明了,缺点也很明显,因为方法和数据的独立性,我们很难去覆盖方法定义。
总结
介绍完联系数据结构与方法的两种方式,我们可以认为,当需要经常根据数据的类去实现同名不同功能的方法的时候,推荐使用凭关系的 class 模型;当方法通常比较固定,而数据多变,相同的方法作用于不同的数据的时候,可以采用凭能力的模型。