闭包
概述
闭包就是函数嵌套函数,内部函数拥有外部函数的引用,导致这个引用就无法被GC回收
作用域(上下文对象)
全局作用域
在全局作用域内声明的函数或者变量都归属于当前的全局对象(global对象)
局部作用域(函数作用域)
在函数作用域内声明的变量或者形参都是归属于当前的上下文对象(context 对象)
函数的执行流程
- 预编译
- 调用执行(通过栈地址找到对应的函数 执行上下文)
- 执行完销毁当前的执行上下文对象
预编译
全局变量的预编译
- 创建对应的全局GO对象(global object)
- 将形参和变量都当作全局GO的属性 形参和变量赋值 指定默认值为undefined
- 形参和实参同步
- 找到函数声明 将对应的值给到函数体
局部变量的预编译
- 创建对应的局部AO对象(Activation object执行上下文对象)
- 将形参和变量都当作局部AO的属性 形参和变量赋值 指定默认值为undefined
- 形参和实参同步
- 找到函数声明 将对应的值给到函数体
GC(垃圾回收器)
主要回收机制
- 标签清除法(通过标记的形式来进行回收 如果当前这个内容没有被使用到 就会被回收)
- 引用计数 (通过不断计数操作来进行回收 有人用就+1 没人用就-1 到0的时候就会被回收)
闭包的特点
保持引用,数据进行缓存,不被垃圾回收机制回收
用途
- 作为缓存(缓存数据量小,加速快)
- 节流
- 防抖
- 函数柯里化
闭包的优缺点
优点:
- 保持了引用,内存不需要重新创建 加载速度快
- 扩大了函数内参数和变量的作用范围
- 利用内部函数来访问外部函数的参数或者变量,避免了数据污染
缺点:
- 内存占用大(一直保持引用),滥用容易造成内存泄露。
- 通过返回函数的形式进行调用,需要不断开辟函数空间 容易内存溢出
防抖
在规定时间内只执行一次,执行的是最后一次(防止高频触发 在高频触发的时候只执行一次)
节流(thorttle)
在限定时间内只执行一次,执行第一次(减少触发次数)
函数柯里化(currying)
将多参数的函数分解成单一参数的函数,主要是可以延迟传入参数(bind也是一个柯里化函数)
函数柯里化的优点
- 延迟传入参数
- 参数复用
参数柯里化的核心
参数个数没到,返回函数,参数个数到了返回结果
反柯里化
将一个原本对象没有的方法进行调用(利用的this指向更改)
Promise
概述
promise 是es6新增的一个类,主要用于处理异步问题(异步代码同步执行)主要解决了回调地狱的问题,他翻译为承诺,主要有三种状态,第一种为成功状态(fulfilled),第二种为失败状态(rejected),第三种为等待状态(pending)(默认状态) promise类的实例化
promise 的相关原型方法(背.重要)
- then 处理成功的方法
- catch 处理失败的方法
- finally 处理状态更改的方法
promise的静态方法
- all 同步并行执行所有的promise 当有一个错误就返回错误的那个promise的结果 当成功就返回所有的结果
- race 竞速 返回最先执行完的promise结果
- rejected 返回一个失败状态下的promise
- resolve 返回一个成功状态下的promise
- allselted 同步并非行执行所有的promise 不管成功失败都返回所有的结果 且状态为成功
总结
- promise 的所有的方法返回的都是一个新的promise对象
- then方法允许传入两个参数(参数类型为函数)他的第一个函数接收resolve的处理 它的第二个函数参数接收reject的处理
- catch接受对应的reject的处理,抛出错误它可以接收(接受错误状态会更改为(rejected)
- then和catch都会发生值穿透问题(传入参数非函数就会发生值穿透)
- then和catch中如果return数据那么就会将数据传递给下一个then 如果抛出错误就会将数据传递给下一个catch
- finally处理状态更改的方法(只要状态发生变化它就会被调用)
回调地狱
回调函数的无限嵌套 造成了回调地狱
- 回调地狱主要是代码的可读性低
- 可维护性低,造成代码没有存在的价值
利用promise来解决回调地狱
- 利用then方法返回的是一个promise 的特性(无限调用then方法)
- 利用then方法中调用return 可以进入下一个then的特性
核心实现
在对应的then方法中调用return。返回一个新的promise来解决回调地狱的问题
ES7新增的async awiat
- async awiat 是一种语法糖
- async 是用于修饰函数的(async修饰的函数返回一个新的promise)
- awiat 是用于修饰promise的(只能在async修饰的函数内使用)
eventLoop(事件轮询)
JavaScript是单线程(js引擎只有一个),同步先执行异步后执行
异步执行机制
异步代码执行机制其实就由webApi进行任务队列(先进先出)的分发
任务队列的组成又分为宏任务队列和微任务队列
- 宏任务队列(属于基础的异步代码JavaScript、事件执行、定时器、延时器...)
- 微任务队列(属于宏任务里面的promise就是微任务)
任务队列的执行机制被称为事件轮询
注意事项
- 先宏后微
- 先进入JavaScript的宏任务,然后推入里面的同步代码,再去找对应的微任务队列
- 将对应的微任务队列的内容按照加入队列的顺序进行推入执行栈(加载顺序),执行完对应所有的微任务开启下一个宏任务
- 如果当前宏任务是setTimeout或者是setInterval那么这个执行的机制取决于间隔的时间(间隔时间一直取决于加载顺序)
- 将当前的宏任务,里面的同步代码推入执行栈 再找到对应的微任务队列执行微任务...不断重复直到微任务队列及宏任务队列都清空