浅谈javascript性能优化

浅谈javascript性能优化

  • 浅谈javascript性能优化
    • 内存管理
      • 概念:
    • 垃圾回收与常见GC算法
    • V8引擎垃圾回收机制
    • performance工具
    • 常用优化方法

浅谈javascript性能优化

内存管理

概念:

	内存是由可读写单元组成,表示一片可操作空间,开发者主动申请空间、使用空间、释放空间
	申请内存空间:多是定义变量如:let obj={}
	使用内存空间: 对变量的读写操作 如:obj,name="jack"
	释放内存空间:变量置空、清空操作如:obj=null
	网站:JSBench网站

垃圾回收与常见GC算法

1.js中内存管理是自动的:创建的对象、数组在代码运行中如果通过引用关系找不到这些变量的时候那么这些对象就是为垃圾
2.对象存在但是语法错误导致找不到该对象,则其也视为垃圾
3.可达对象:可以访问到的对象(引用、作用域链),可达的标准是从根出发是否能找到,所谓的根就是指当前的全局变量对象(全局执行上下文)
4.举例:let obj={name:'xiaoming'} //出现引用,此处obj既是可达的;   let ali=obj,obj=null,此时{name:'xiaoming'}仍然可达
5.function objGrop(obj1,obj2){
   	obj1.next=obj2
   	obj2.pre=obj1
   	return {
   		01:obj1,
   	 	02:obj2
	}
   }
   let obj=objGrop({name:'obj1'},{name:'obj2'})
   console.log(obj)
   
   ![在这里插入图片描述](https://img-blog.csdnimg.cn/2021041516595234.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NTRE5pc1NCYQ==,size_16,color_FFFFFF,t_70#pic_center)
   obj1与obj2相互引用,如果obj删除掉O1属性obj2删除pre属性那么此时是获取不到obj1的此时obj1就是不可达的,此时是为垃圾
   6.GC算法:程序中不在使用的对象以及程序中不能再访问的对象均作为垃圾,常见GC算法:
          引用计数:核心设置引用数,判断当前引用数是否为0,引用关系改变时修改引用数字:
               const user1={age:11}
               const user2={age:22}
               const user3={age:33}
               const nameList=[user1.age,user2.age,user3.age]
               function fn(){
               const num1=1
               const  num2=2
			}
			fn() 函数调用后num1、num2的引用计数就成为0,此时视为垃圾而user1,user2,user3仍然被引用所以她们的引用计数不为0也就不会当做垃圾;
			***引用计数算法优缺点:优点:发现垃圾时立即回收、最大限度减少程序暂停;缺点:无法回收循环引用的对象、时间开销大例如:
			      a.循环引用:function fn(){
						const obj1={}
						const obj2={}
						obj1.name=obj2
						obj2.name=obj1
						return 'hello'
					}
					fn() /函数执行完时无法回收循环引用的对象obj1和obj2因为两者互相引用所以无法回收
          标记清除:原理:分标记和清除两个阶段,第一阶段遍历所有对象找标记活动对象(与可达对象一个道理),第二阶段遍历所有对象清除没有标记的对象;回收相应的空间,将回收的空间放到空闲链表中方便后面的使用:
                  优点:补充了引用计数的不足能解决循环引用不能回收的问题,减少程序卡顿            缺点:地址不连续(空间碎片化),不会立即回收空间
          标记整理:第一阶段与标记清除一致,清除阶段移动对象的位置使活动对象连续,非活对象连续,后进行空间的回收
          分代回收

V8引擎垃圾回收机制

 1.回收策略:分代回收,内存分为新生代、老生代,根据不同对象进行不同的策略,V8内存一分为2,小空间(32M/64位系统,16M/32位系统)--指的是存活时间较短的对象
           新生代回收策略(空间换时间):复制+标记整理:from使用状态,to空闲状态空间,活动对象存于from空间,标记整理后将活动对象拷贝到to,from与to交换空间完成释放,拷贝过程中可能出现晋升:就是将新生代对象移动至老生代,一轮GC还存活的新生代需要晋升,to空间使用率超过25%(怕转成空闲时,空间不够用)(理想情况下新生代数据不需要晋升---指的是基本数据类型的数据,基本数据类型例如string,boolean基本上是新生代数据,)
           老生代回收(不适合复制算法):1.4G/64位系统,700M/32位系统,老生代对象是指存活时间较长的对象(闭包):主要采取标记清除、标记整理、增量标记算法实现;首先用标记清除完胜垃圾空间的回收,标记整理算法进行空间优化(新生代区域的内容->老生代时,若此时老生代区域不足以容纳转移来的新生代内容),
    增量标记进行效率优化;增量标记:垃圾回收会阻塞js运行,增量标记就是将整段的垃圾回收拆成多段,进行组合式的垃圾回收实现js与垃圾回收交替运行

performance工具

1、内存泄漏:内存使用持续升高
2、内存膨胀:在多数设备商存在性能问题
3、频繁垃圾回收:通过内存变化图分析
4、工具:浏览器任务管理器(shift+esc)、timeline时序图记录、堆快照查找分离DOM、判断是否存在频繁的垃圾回收
             堆快照:界面元素存活在DOM树上,可分为:垃圾对象时的DOM节点,分离状态的节点:去除分离DOM:变量置空
             是否存在频繁的垃圾回收:timeline中频繁的上升下降,任务管理器中数据频繁的增加减小

常用优化方法

1、为何慎用全局变量:因为全局变量定义在全局执行上下文中,是所有作用域链的顶端,全局上下文一直存在于上下文执行栈,直到程序退出,如果某个局部作用域出现了同名变量则会遮蔽或者污染全局(测试代码效率:jsperf.com)
2、避开闭包陷阱:不用的置null
3、避免属性访问方法的使用:例1:function Person(){
		this.name='icoder'
		this.age=18
		this.getAge=function(){
		return this.age
		}
}
const p2=new Person()
	const Page1=p1.getAge
	
例2: function Person(){
		this.name='icoder'
		this.age=18
	}
	const p2=new Person()
	const Page2=p2.age
	经过对比第二种毕第一种性能更好
4、通过原型对象添加附加方法://案例1的效率比案例2的低
          例1:var fn1=function(){            
          		this.foo=function(){
          		 console.log(11111)
					}
          	}
        let f1= new fn1()
        var fn2=function(){     
          	}
          	fn2.prototype.foo=function(){
          		 console.log(11111)
					}
        let f2= new fn2()
 5、缓存数据
 6、优化for循环
 7、选择最优的循环方法:数组遍历foreach优于for,for优于forin
 8、文档碎片优化节点添加:document.createDocumentFragment()
 9、克隆优化节点操作(克隆后自带样式属性故而性能更好些):
 10、直接量替换new object、new Array:例如:var a1= new Array(3); a1[0]=1;a1[1]=2;a1[2]=3; var a=[1,2,3] //前面的性能慢于后面的
 11、减少判断层级:(if 条件判断减少嵌套)
 12、减少作用域链查找层级
 13、减少数据读取次数(字面量,数组元素,局部变量,对象属性):
 14、尽量用字面量少用构造式(new object、new String、new Number):
 15、减少循环体活动
 16、减少声明及语句数
 17、采用事件委托绑定事件

你可能感兴趣的:(es6,javascript)