面向对象的矛盾
面向对象的应用程序大多是命令式,因此它的稳定性在很大程度依赖自身的封装性和继承的可变状态
最后通过实例方法来暴露或修改这些状态。
你或许曾看过Array.prototype.slice.call(arguments)
这样的代码,这是典型的改变原型方法实例指向的调用。
所以,面向对象的的实例方法数据与行为(action)是以一种内聚的形式耦合在一起的。
在看函数式编程,它不需要向调用者隐藏数据(调用者自身传入参数就行了),由于纯函数的不可变性,数据与行为是松耦合的。
如
A.prototype.getFullName = function() {
return this.name
}
可以拆分为以下函数
var getFullName = function(person) {
return person.name
}
面向对象的关键在于方法与实例的紧密绑定,而函数式编程则更倾向于通过广义的堕胎函数交差应用不同的数据类型,同时避免使用this
实战演练
class Person {
peopleInSameCountry(friends) {
var result = []
for(let idx in friends) {
var friend = friends[idx]
if(this.address.country === friend.address.country){
result.push(friend)
}
}
return result
}
}
class Student {
constructor(name,country,ssn,school) {
super(name,country,ssn)
this.school = school
}
}
var curry = new Student('Haskell','US','111-11','Pen State')
var turing = new Studeng('Alan','US','222-333','Princeton')
turing.peopleInSameCountry([curry])
函数式解决方案 分解成很多小的函数
function selector(country) {
return function(student) {
student.country === country
}
}
var findStudentsBy = function(friends,selector) {
// 使用数组的filter方法
return friends.filter(selector)
}
findStudentsBy([curry],selector('US'))
面向对象和函数式编程的一些重要性质比较,这些性质是贯彻本书的主题
类型 | 函数式 | 面向对象 |
---|---|---|
组合单元 | 函数 | 对象(类) |
编程风格 | 声明 | 命令 |
数据行为 | 独立且松耦合的纯函数 | 与方法紧耦合的类 |
状态管理 | 将对象视为不可变的值 | 主张通过实例方法改变对象 |
程序流控制 | 函数与递归 | 循环与条件 |
线程安全 | 可并发编程 | 难以实现 |
封装性 | 一切都是不可变的,没有必要 | 需要保护数据的完整性 |
网友评论