1. 函数式编程简介
- 目的:使用函数来抽象作用在数据之上的控制流与操作,从而在系统中消除副作用并减少对状态的改变
- 特点: 声明式编程 / 纯函数 / 引用透明 / 不可变性
声明式编程是将程序的描述与求值分离开来的
- 纯函数具有的特性:
- 仅取决于提供的输入,而不依赖于任何在函数求值期间或调用间隔时可能变化的隐藏状态和外部状态
- 不会造成超出其作用域的变化,例如修改全局对象或引用传递的参数
在js中基本数据类型是不可变的类似于:string,number等等,但是其他对象例如数组等等是可变的
函数式编程的基本原则:函数式编程是指为创建不可变的程序,通过消除外部可见的副作用,来对纯函数的声明式的求值过程
- 优点
- 促使将任务分解成简单的函数
- 使用流式调用链来处理数据
- 通过响应式范式降低事件驱动代码的复杂性
- 有助于提高代码的可测试性和可维护性
- 可以利用响应式编程组合各个函数来降低事件驱动程序的复杂性
- 可以通过高阶函数来提高代码的模块化和可重用性
面向对象的核心:就是创建派生对象作为程序中代码重用的主要手段。
- 面向对象的应用程序大多是命令式的,会将对象的数据与其具体的行为以一种内聚的包裹的形式紧耦合在一起
- 函数式推荐使用解耦,独立的操作少量类型的函数
面向对象推荐创建特殊的类型(通过继承)实现细粒度的行为
- js可以使用object.freeze来实现值对象机制(一旦声明,其状态就不会改变)
// Object.freeze属于浅冻结
//其方可以冻结一个对象,冻结指的是不能向这个对象添加新的属性.
//不能修改/删除新增属性,以及不能修改对象已有属性的可枚举性,可配//置性,
//也就是说,这个对象是不可变的
//例如
var obj = {
name:'abc',
age:14,
dsc:'this is aaa'
}
var obj3 = Object.freeze(obj)
obj3.age = 20;
obj3 // { name:'abc',age:14, dsc:'this is aaa'}
obj1 // { name:'abc',age:14, dsc:'this is aaa'}
为什么Object.freeze是浅冻结
class Person {
constructor(name) {
this._name = name;
this._address = null;
}
get name() {
return this._name;
}
set address(address) {
this._address = address;
}
get address() {
return this._address;
}
}
class Address {
constructor(country, city) {
this._country = country;
this._city = city;
}
get country() {
return this._country;
}
get city() {
return this._city;
}
}
var person = new Person(20)
person.address = new Address('US','NJ')
Object.freeze(person); // 将person冻结
person.address._country = 'china';
console.log(person.address._country) // china
// 可以看出address其实是可以改变的,
//虽然person已经被冻结了,但是_address并没有冻结,所以其实是浅冻结
- 函数引用
8.1. 函数式引用(Lense):是函数式程序设计中用于访问和不可改变的操纵状态数据类型属性的解决方案,即采用一个能够合理管理和赋值状态的内部存储部件
8.2 高阶函数
高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回。
函数具有值的行为,也就是说,函数就是一个基于输入的且尚未求值的不可变的值
- js 的作用域
js作用域分为三类:全局作用域 / 函数作用域 / 伪块作用域
9.1 全局作用域
全局作用域是最简单的作用域,也是最差的。任何对象和在脚本最外层声明的变量都是全局作用域的一部分,并且可以被所有的js访问
9.2 函数作用域
在函数中声明的任何的任何变量都是局部且外部不可见的。同时,在函数返回后,其声明的任何局部变量都会被删除
函数的作用域机制:
- 首先检查变量的函数作用域
- 如果不是在局部作用域内,则逐层向外检查各词法作用域,搜索该变量的引用知道全局作用域
- 如果无法找到变量引用,那么js返回undefined
9.3 伪块作用域
js有一个内部机 制就是将所有声明的变量和函数提取到当前块级作用域的顶部。
- 闭包
- 闭包优势:模拟私有变量 / 异步服务端调用 / 创建人工块作用域变量
- 闭包的用途:信息隐藏 / 模块化开发 / 能够将参数化的行为跨数据类型的应用与粗粒度的函数之上等等
10.1 模拟私有变量
闭包可以实现私有变量
还可以用来管理全局命名空间,避免在全局范围内共享数据。在封装内部变量同时,允许对外公开必要的功能合集,从而有效减少全局引用
10.2 异步服务端调用
js中的高阶函数可以作为回调函数传递到其他函数中。回调函数和钩子函数一样,可以非侵入式的处理各种事件
10.3 模拟块作用域变量
由于js缺乏块作用域语义,需要人为的制造出块作用域,但是let缓解许多传统的循环机制问题,或者说foreach的函数方式则可以对闭包以及js的函数作用域加以利用,可以在循环体内包裹函数作用域来模拟块作用域
arr.foreach(function(ele,i){
...
})
网友评论