- 从编程模式看:JS是结构化、事件驱动的动态语言,支持声明式和指令式两种模式,所以JS是一个多模式的语言。
- 面向对象和函数式是常用的两种模式。
函数式编程
- 基本概念:函数是什么?函数是数据集到目标的一种关系。在函数式编程中,常把对函数的各种干扰称为副作用。函数内部较为相对可控,外部环境则比较不可控。
- 函数的副作用分为三大类:
- 全局变量。
- IO影响:用户的输入行为或者是文件系统、网络链接以及stream的stdin(标准输入)和stdout(标准输出)。
- 网络请求。
- 如何解决副作用:
- 纯函数:解决内循环,确保函数的返回结果的变化只依赖自身参数,并且执行过程中没有副作用。通过减少对外界不确定因素的依赖来减少副作用。
- 不可变(immuatbility):解决外循环,在减少函数被外界影响的同时,确保函数自身对外界的影响。
- 总结:纯函数只对值影响一次(数学知识中的幂等的概念),不可变则不影响(状态管理,记录状态改变,而不修改状态)。
- 总结:
- 函数式编程的最核心的地方,就是输入输出和中间的算法,我们要解决的核心问题就是副作用。
- 纯函数和不可变式解决副作用的两个重要概念:纯函数强调自身的稳定性,对结果只影响一次。而不可变强带哦的是和外界的交互中,尽量减少相互间负面的影响。
面向对象编程
- 基本概念:对象是主体,函数可以看成是工具,工具和方法都是服务于对象的。
- 封装、重用和继承
- 如果说函数加对象形成了生产力,那么封装、重用和继承可以用来组成生产关系。
- 封装:组件和模块是通过封装导入加载到页面的。
- 重用:把重复使用的功能抽象到一个类里,每次只创建一个它的实例对象使用。
- 继承:通用功能会放到抽象类中,而一些特定的行为或属性,可以通过继承放到实现类中。
- 组合:继承会出现抽象的层级过多导致代码难以理解和父类除了问题导致子类出现问题,为此面向对象中还有一个组合的概念,一个字累不是继承的某个父类,而是组合多个类形成一个类。通常组合是优于继承的。
- 基于原型的继承:
- JS中对象和类没有拷贝的从属关系,而是原型链接关系。即使es6引入了类,但是底层仍旧是基于原型的面向对象。es6中类的数据类型就是函数,类本身就指向构造函数。
- es6中的class:它在es6被当成关键字引入,但只是语法糖,JS仍旧是基于原型的。
-
类的本质就是个function
-
类的构造函数指回本身
-
通过原型对象添加方法
-
构造函数创建的实例对象有_proto_原型指向构造函数的原型对象
-
- 原型 与原型链
- 在JS中两个对象之间创建关联,一个对象通过委托单方式访问另一对象的属性和函数被称为继承。
- 当谈及到继承时,JS只有一种数据结构也就是对象。每个实例对象都有一个_proto_原型属性,该属性指向构造函数的原型对象(prototype)。该原型对象都有一个自己的原型属性(proto)指向上一层构造函数的原型对象,如此层层向上直到一个对象的原型对象为null终止。
- 实例对象的_proto_原型属性指向构造函数的原型对象开始,借助原型对象的_proto_属性层层向上直到指向的原型对象为null终止,被称为原型链。JS就是通过原型链来实现继承。
- 每个原型对象(prototype) 都有一个constructor属性指向关联的构造函数。
- _proto_称为隐式原型,prototype称为显式原型,可获取的constructor其实是从原型对象中获取的,这也反应了原型链的机制。
- prototype 无法直接修改、引用。从es6开始object.getPrototypeOf()和Object.setPrototypeOf()来访问、修改原型对象。
总结
- 函数式编程和面向对象编程,一个是管理和解决副作用,一个是服务于业务对像。