js高阶-总结精华版
js
高级语言:
c,c++,java,js
- 编译型语言
java,c
直接编译成为可执行文件 - 解释型语言
js
边读取代码边编译,然后再执行
代码编译过程
- 创造全局的变量对象:
GO
global Object
GO
中存放了全局的代码,内置函数等 - 遇到函数定义,开辟函数的内存存储空间
当前的作用域
+js代码
在GO
中存放函数地址
代码执行过程
创建全局执行上下文,
压入执行上下文栈,
全局执行上下文中有
- 变量对象go:内部属性关联了函数与变量的
声明
开始一行一行执行代码,
给变量赋值,
如果遇到函数执行,创建函数执行上下文,压入执行上下文栈
函数执行上下文中有- 变量对象ao:内部关联了函数与变量
2)作用域链:当前作用域ao+父级作用域(在编译期间决定)
3)this
当代码执行完毕,弹出执行上下文栈
- 变量对象ao:内部关联了函数与变量
编译
先生成go,若go中有函数,这在内存中开辟空间存储函数对象
执行
函数执行之前生成ao
浏览器
工作原理
- 输入url , 通过dns 解析,得到ip
- tcp 三次握手建立连接
- 发起http请求
- 返回HTML文件
一般返回html文件
浏览器解析文件
- 遇到css 再发请求获取css文件
- 遇见script 再发请求获取js文件
内核
webkit blink
分为两部分:
- 解析html : 渲染引擎
- 解析js : js引擎(V8)
jscore (js引擎)
作用 : 将js代码编译成机器指令,供cpu执行
- 词法分析 | 语法分析 解析js代码
- 生成抽象语法树ast
- 转化器转为字节码
- 字节码通过汇编转成机器指令
如果有出现频率比较高的js代码,就收集起来
但是如果出现例如传入的数据类型不一样,就得在这个基础上重新生成字节码
(因此如果都是用ts的话,这部分的性能花销就不存在了)
v8 引擎为什么很快 : 实现了即时编译 jit
将字节码转换成机器码,缓存起来
webcore(渲染)
- 解析html 生成dom树
- 解析css 生成cssom树
- 两者结合生成渲染树
- 渲染树 通过 layout 计算出节点的大小位置
- 通过 painting 绘制在页面上
在绘制的过程中可以将布局后的元素绘制到多个合成层中,通过GPU加速
垃圾回收
分区
新生代
老生代区
垃圾回收算法
引用计数算法
对象中存放计数器,默认初始值为0
当其他对象使用到这个对象,
这个对象的计数器就++,不再使用–
当计数器变为0,这个对象就被回收掉
循环引用:内存泄漏
标记清除算法
设置一个根对象,
gc会定期的从这个对象开始找有引用到的对象做标记,
对于没有引用到的对象,认为是不可达的对象,清除掉
其他
回流 vs 重绘 -->性能优化
触发合成层的操作
函数
闭包
一个普通函数可以访问外层作用域中的自由变量,这个函数就是一个闭包
- 自由变量:跨了自己作用域的变量都是自由变量
导致内存泄漏,解决方法
- 最小化闭包作用域
- 解除引用 设置null
- 使用弱引用
闭包的使用场景
- 私有变量
- 模块化
this指向
普通函数
- 默认指向
作为独立函数调用,this指向全局对象 - 隐式指向
作为对象的方法调用 , this指向对象 - 显式指向
通过call,apply,bind 显式指向传入的对象 - new + fn 指向
指向创建出的对象
箭头函数
没有自己的this,继承外层作用域的this
事件循环
js是单线程的,同一时间只能做一件事情
当遇到耗时长操作
当前线程就会被阻塞
于是,出现异步操作
异步操作
交给浏览器其他线程来处理,
处理完后将异步任务放入事件队列
js引擎在调用栈为空的时候会检测事件队列,从中取任务执行
这个过程事件循环
宏任务与微任务
事件队列,分为宏任务队列与微任务队列
从宏任务开始,执行完后检测微任务队列,为空再执行下一个宏任务
宏任务
setTimeOut,ajax,UI Rendering,Dom监听等
微任务
Promise的then回调,queueMicroTask,Mutation Api等
其他
new 的过程
作用域与作用域链
对象
原型
- 对象都有内置属性
[[proto]]
,浏览器中是_proto_
指向一个原型对象 - 函数身为对象有_proto_属性,还有
prototype
属性,指向一个原型对象 - 原型对象也是对象有_proto_属性指向自己的原型对象,同时有
constructor
属性指向自己的构造函数
ES6
class
extends super
babel
一个工具,可以将es6+代码转换成向后兼容的js版本
其他
let const
weakSet weakMap
proxy 与reflect
proxy
es6新增类,用来创建代理对象,
通过给对象创建代理对象,之后所有对对象进行的操作都可以通过代理对象进行
new Proxy(target,handler)
let proxyObj=new Proxy(obj,{//获取值 target是目标对象 key是属性get(target , key){console.log(`检测到get`);return target[key]},//设置值set(target,key,newVal){console.log("检测到set");target[key] = newVal},//监听in 的操作符has(target,key){console.log("监听in操作");return key in target},//监听deletedeleteProperty(target , key){console.log("监听到delete操作");delete target[key]},})
Reflect
eS6新增的内置对象
,所有方法都是静态方法,像Math
提供很多操作js对象的方法
,类似Object中操作对象的方法
- Reflect.getPrototypeOf(target) — Object.getPrototypeOf()
- Reflect.defineProperty() — Object.defineProperty()
为什么要有这个对象
- 早期的规范中,没有考虑到对
对象本身操作
如何设计更加规范,于是将API放到了Object上面,导致Object类越来越臃肿,而它做为所有类的父类,会被继承到子类中,东西过多加重子类负担 - Object做为构造函数,将这些操作放在它上面不太合理
所以新增Reflect 来集中管理这些操作
let obj={name:'zhangsan',age:18}console.log("检查name属性是否存在",Reflect.has(obj,'name')); //检查name属性是否存在 trueconsole.log("获取name属性",Reflect.get(obj,'name'));//获取name属性 zhangsanReflect.set(obj,'name','lisi');console.log(obj.name);//lisiReflect.deleteProperty(obj,'age');console.log(obj.age);//undefinedconsole.log("检查age属性是否存在",Reflect.has(obj,'age')); //false
promise
处理异步操作的新增类
三种状态
- Pengding 初始状态,异步操作暂时没有完成
- Fulfiied 异步操作完成,获得成功结果
- Rejected 异步操作完成,获得失败的结果
只能由Pengding 转到fulfilled / rejected ,状态一旦改变,不能再变
当异步操作完成,异步操作的结果作为参数传入resolve()/reject()
触发.then(onFulfilled)
中的成功回调函数
触发.catch(onRejeected)
中的失败回调函数
迭代器与生成器
迭代器
一个对象,这个对象可以遍历某种数据结构
这个对象要符合迭代器协议
迭代器协议
- 对象中有next方法,接收无参或者一个参数,
- next() 返回一个对象,对象中有
{value:当前产生的值,done:布尔值,表示是否当前所有值已经被迭代完毕}
//封装成函数
function createIterator(arr){let i=0;return {next(){if(i < arr.length){return {value:arr[i++],done:false}}else{return {value:undefined,done:true}}}}}
可迭代对象
一个对象,实现了[Symbol.iterator方法]
符合可迭代协议,必须实现这个方法+返回迭代器对象
可迭代协议
- 遍历的目标对象
- 索引指针
- 迭代器
const iterableObj={//需要遍历的目标数组names:[1,2,3,4],[Symbol.iterator]:function(){//索引指针let index = 0;//迭代器return {next:()=>{if(index<names.length){return {done:false;value:this.names[index]}}else{return {done:true;value:undefined}}}}}
}
生成器
生成器
特殊的迭代器对象,除了next,还有return,throw方法
生成器函数`
- 一个函数,可以控制函数的执行
- 返回一个生成器对象
//1.生成器函数定义function* generatorFn(){console.log("start------");const value = 100;console.log("first------");//1.yield 可以接收值const a= yield //生成器暂停const value2 = 200;console.log("second------",a);//2.yield 可以返回值yield value2console.log("end-------");return 123}//2.生成器函数调用// generatorFn()//没反应const generator = generatorFn()console.log(generator.next(1));console.log(generator.next());console.log(generator.next());