目录
一、函数式编程的一些概念
1、柯里化
柯里化指的是:将多参数的函数转换成单参数的形式(多参转一参)。
(1)、ES5实现函数柯里化
function currying(fn, n) {
return function (m) {
return fn.call(this, m, n);
};
}
function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
}
const factorial = currying(tailFactorial, 1);
factorial(5) // 120
上面代码通过柯里化,将尾递归函数tailFactorial变为只接受一个参数的factorial。
(2)、ES6实现函数柯里化
function factorial(n, total = 1) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}
factorial(5) // 120
上面代码中,参数total有默认值1,所以调用时不用提供这个值。
2、尾调用
尾调用指的是:在某个函数的最后一步是调用另一个函数。
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
(1)、非尾递归实现 Fibonacci 数列
function Fibonacci (n) {
if ( n <= 1 ) {return 1};
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
Fibonacci(10) // 89
Fibonacci(100) // 超时
Fibonacci(500) // 超时
(2)、尾递归实现 Fibonacci 数列
function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
if( n <= 1 ) {return ac2};
return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}
Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity
二、函数式编程与面向对象编程的优缺点
1、函数式编程的优缺点
(1)、函数式编程的优点
①、由于数据全部都是不可变的,所以没有并发编程的问题,多线程是安全的。
②、对于快速迭代的项目来说,函数式编程可以实现函数与函数之间的热切换而不用担心数据的问题,因为它是以函数作为最小单位的,只要函数与函数之间的关系正确即可保证结果的正确性。
③、函数式编程的表达方式更加符合人类日常生活中的语法,代码可读性更强。
④、实现同样的功能,函数式编程所需要的代码比面向对象编程要少很多,代码更加简洁明晰。
(2)、函数式编程的缺点
①、由于所有的数据都是不可变的,所以所有的变量在程序运行期间都是一直存在的,非常占用运行资源。
②、函数式的先天性设计导致性能一直不够。
③、如果对函数式编程的理解不够深刻就会导致跟面相对象一样晦涩难懂的局面。
2、面向对象编程的优缺点
(1)、面向对象编程的优点
①、程序的灵活性和可维护性更好。
②、由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。
(2)、面向对象编程的缺点
①、面向对象编程以数据为核心,所以在多线程并发编程中,多个线程同时操作数据的时候可能会导致数据修改的不确定性。
②、在现在的软件工程中,由于面向对象编程的滥用,导致了很多问题。首先就是为了写可重用的代码而产生了很多无用的代码,同时很多人并没有完全理解面向对象思想,为了面向对象而面向对象,使得最终的代码晦涩难懂,给后期的维护带来了很大的问题。所以对于大项目的开发,使用面向对象会出现一些不适应的情况。
③、面向对象虽然开发效率高但是代码的运行效率比起面向过程要低很多,这也限制了面向对象的使用场景不能包括那些对性能要求很苛刻的地方。
三、基于 python 体会函数式编程与面向对象编程
函数式编程:
def login():
user = input('请输入用户名:')
pwd = input('请输入密码:')
if user == 'alex' and pwd == 'sb':
print('登录成功')
else:
print('登录失败')
面向对象编程:
class Account:
def login(self):
user = input('请输入用户名:')
pwd = input('请输入密码:')
if user == 'alex' and pwd == 'sb':
print('登录成功')
else:
print('登陆失败')
obj = Account()
obj.login()
对比两种编程方式可知:
- 函数:定义更简单,调用更简单。
- 面向对象:方便归类,将某些类似的函数写在一起。
四、JavaScript 中的函数式编程与面向对象编程
1、函数式编程
函数式编程组织代码的方式,至少在Node中,也有两种模式。
(1)、导出一个函数
第二种方式是从一个模块中导出一个函数:
// CommonJSconst utilFunction = () => ...module.exports = utilFunction// ES6const utilFunction = () => ...export default utilFunction
const utilFunction = () => ...
module.exports = utilFunction
// ES6
const utilFunction = () => ...
export default utilFunction
(2)、导出多个函数
第二种方式是从一个模块中导出多个函数:
// CommonJSconst utilFunction = () => ...const anotherHelper = () => ...module.exports = { utilFunction, anotherHelper}// ES6export const utilFunction = () => ...export const anotherHelper = () => ...
const utilFunction = () => ...
const anotherHelper = () => ...
module.exports = {
utilFunction,
anotherHelper
}
// ES6
export const utilFunction = () => ...
export const anotherHelper = () => ...
(3)、导出变量
有些人们会把变量与函数用同样的方式导出,而有些更喜欢纯函数的人或者倡导延迟计算的人会导出函数:
// pragmaticexport CONFIGURATION_THING = 'some value'// puristexport configurationThing = () => 'some value'
export CONFIGURATION_THING = 'some value'
// purist
export configurationThing = () => 'some value'
2、面向对象编程
(1)、导出单一类模块
可以说,至少在Node中,面向对象的方式通常包含两个基本设计模式。第一种方法是创建一个类,然后作为默认导出公开:
// CommonJSclass SomeThing { ... }module.exports = SomeThing// ES6class SomeThing { ... }export default SomeThing
class SomeThing { ... }
module.exports = SomeThing
// ES6
class SomeThing { ... }
export default SomeThing
(2)、导出多个东西(类、函数、事件和变量)
第二种方法是从同一模块中公开许多东西,包括类、函数、事件和变量:
// CommonJSclass SomeThing { ... }const utilFunction = () => ...const CONFIGURATION_VAR = ...module.exports = { SomeThing, utilFunction, CONFIGURATION_VAR}// ES6export class SomeThing { ... }export const utilFunction = () => ...export const CONFIGURATION_VAR = ...
class SomeThing { ... }
const utilFunction = () => ...
const CONFIGURATION_VAR = ...
module.exports = {
SomeThing,
utilFunction,
CONFIGURATION_VAR
}
// ES6
export class SomeThing { ... }
export const utilFunction = () => ...
export const CONFIGURATION_VAR = ...
更多关于面向对象的知识请戳这里:js 面向对象(设计模式) 与 继承(原型与原型链)https://blog.csdn.net/mChales_Liu/article/details/103423611
【参考文献】