JavaScript 函数的执行原理、闭包、防抖节流

196 阅读3分钟

函数的执行原理:

   1、程序加载时:
	创建执行环境栈(ECS):保存函数调用顺序的数组
	首先压入全局执行环境(全局EC)
	全局EC中引用着全局对象window
	window中保存着全局变量

   2、定义函数时:
	创建函数对象:封装函数的定义
	在函数对象中创建scope属性,记录着自己来自的作用域
	全局函数的scope都是window

   3、调用函数前
	在执行环境栈ECS压入新的函数的EC
	创建活动对象AO:保存着本次函数调用时用到的局部变量
	在EC中添加scope chain属性引用AO
	设置AO的parent属性为函数的scope引用的对象

   4、调用时:
	变量的使用规则:优先使用局部的,局部没有才找全局,全局没有才报错

   5、调用完:
	函数的EC会出栈,AO会自动释放,局部变量也就自动释放了

   ***面试:作用域链scope chain:
	以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,就称之为叫做作用域链
	作用:查找变量
            

函数的执行原理.png

*闭包:

  目的:保护一个可以【反复使用的局部变量】的一种词法结构
        结合了全局和局部的优点
	唯一的缺点:受保护的变量永远不能释放,用多了会导致内存泄漏
	尽量的少用:只有一个点会用到防抖节流
        如何:31、创建一个外层函数
	  2、在其中创建一个受保护的局部变量
	  3、外层函数调用要返回内层函数,此内层函数在操作受保护的变量

	鄙视时:
	  1、判断闭包,找到受保护的变量,确定其值
	  2、外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
	  3、同一次外层函数调用,返回的内层函数,都是在使用同一个受保护的变量

	固定语法:
	  function 外层函数(){
		受保护的变量;
		return function(){
			不断的操作受保护的变量
			return 结果;
		}
	  }	

	  var 内层函数=外层函数();
              
          例题:function factory(){
			var i=0;
			return function(){
				i++;
				return i;
			}
		}
		
		var icbc=factory();
		console.log(icbc());
                    var jh=factory();
		console.log(jh())

正式开发:防抖节流:减少DOM树的渲染,DOM数据渲染的次数越频繁页面的效率越底下

	   3个事件需要去做防抖节流:
		1、elem.onmousemove - 鼠标移动事件,每次移动就会触发
		2、input.oninput - input每次修改内容就会触发
		3window.onresize - 屏幕每次改变大小就会触发

		固定公式:
		function fdjl(fn:Function){
			let timer=null;//3
			return function(){
				//判断有没有定时器,如果有定时器就清除定时器
				if(timer){clearTimeout(timer)}
				timer=setTimeout(function(){
			          fn()//你要做的操作
				},毫秒数)
				console.log(timer);//定时器的序号
			}
		}
	        function f1(){
               console.log('发送请求')
            }
		const animate=fdjl(f1);//用一个变量来接收 `fdjl` 返回的那个函数
                    
                    
用法:  <button @click=animate></button>