面向对象编程(OOP)和函数式编程(FP)

面向对象编程(OOP)和函数式编程(FP)

编程的本质万变不离其宗就是,操纵一坨数据。

当然操纵的方式有许多,存储的方式也五花八门,但是本质不变,就是访问数据(读取以及改变)。

词条:操作数据

​ 面向对象:实例、原型、构造函数、原型链

​ 函数式:作用域、作用域链、参数、递归、闭包、函数调用

1、数据存放形式

​ 1、对于OO(面向对象,下同),数据存放在对象的属性(成员变量)里面,以及静态成员(全局变量)

​ 2、对于函数式,数据存放在闭包(各级作用域)里面,作用域包括全局作用域。

2、数据访问形式

​ 数据存放方式决定了访问的方式。

​ 1、对于OO来说,访问数据(全局变量除外)需要先获取对象的引用,然后再进行操作(直接访问——公共属性,或者调用成员函数/方法访问——私有属性)

​ 2、对于函数式,访问数据是直接访问(通过函数入参或者作用域链查找)

下面上一段代码
// OO
class Foo {
  constructor(){
    this.bar = 0
  }
}
let foo = new Foo()
foo.bar ++

// 函数式

let bar = 0
function foo(){
    bar ++
}
foo()

从中我们可以看出一些东西,OO是通过持有,以及传递对象的方式去让别的对象来操作数据,而对象也会是其他对象的成员,层层嵌套。当你想要访问某一个数据的时候,就需要顺着对象的引用链条去找,一步步去操作。

函数式传递的则是函数,调用函数即操作数据,传递函数的时候其实隐含着传递了函数创建的时候所附带的作用域,这个在表面上看不出来,在底层是有的。

OO所谓的对象,本质上就是函数式中的作用域。

为了理解这句话,我们来看高阶函数的本质

function foo(x){
  let bar = x
  return function(){
     return bar
  }
}
let Bar = foo(1)
console.log(Bar())//1

当调用foo(1)的时候返回一个函数,这个函数可以访问foo函数内部的bar变量,这就是高阶函数。如果翻译成OO思想大家就知道怎么回事了。

class Foo{
  constructor(x){
    this.bar = x
  }
  Bar(){
    return this.bar
  }
}
let foo = new Foo(1)
console.log(foo.Bar())

看上去是不是差不多。其实在C#中对lambda表达式的编译就是这个原理。会内部创建一些类。

当然高阶函数的写法肯定不会这么啰嗦,会写的比较优雅。(这就是本质区别

let foo = bar=>()=>bar
let Bar = foo(1)
console.log(Bar())//1

所以OO编程,是面向作用域编程,而函数式编程,是面向功能编程。

参考:https://zhuanlan.zhihu.com/p/57708956

​ https://blog.csdn.net/mrgglxy/article/details/80571290

总结:

函数式编程把数据与操作逻辑区分开, 然后各种组合;

面向对象把数据与操作逻辑合并到一块, 形成一个封装, 再各种应用;

分开使用显然比合在一起使用要灵活, 真正需要封装的时候再去谈面向对象…

偏偏人们已经把面向对象当成了组织代码的方式了, 不需要封装的时候也非要用面向对象…

函数式编程对开发者要求更高一些,需要对程序的理解更深入。面向对象则更浅显,所以为了让公司里面良莠不齐的开发人员统一协作,就逐渐采用了以面向对象为主的开发模式。

闭包和对象都是把数据从stack复制到heap里去

程序本质就是操作数据,oop和fp都把数据封装到属性中,oop通过对象封装和操作属性。fp通过函数来操作属性。

你可能感兴趣的:(javascript,函数式编程,面向对象编程)