闲谈js中执行期上下文,作用域,作用域链,闭包

闲谈js中执行期上下文,作用域,作用域链,闭包(并不详细)

一.预编译期间产生执行期上下文

  • 代码执行之前的准备工作(预编译),确定当前环境下标识符(变量、常量、数组、函数、对象等)的取值,this的指向

  • 当函数每次执行时,都会创建一个新执行期上下文,当函数执行完毕,它所产的执行上下文被销毁

  • 执行期上下文分为: 全局执行上下文(全局预编译产生)和函数执行上下文(函数预编译产生)

    • 函数预编译有四步骤,而全局预编译有只有三步骤
					1.函数预编译四部曲
	1. 创建AO(activation object)对象 (函数执行期上下文)  	
	2. 找形参和变量声明,将变量声明和形参作为AO对象的属性名,值为undefined  	
	3. 将实参和形参统一  	
	4. 在函数体里面找函数声明,值赋予函数体 (函数声明定义的函数名与形参和变量声明一样的话,
       覆盖掉他们的值)
	注意:定义的形参和变量声明以及函数名如果相同,也只能作为AO对象的一个属性名(对象属性的唯一性)

					2.全局预编译三部曲
	1. 创建GO(Gloabl object)对象(全局执行期上下文)  	
	2. 找变量声明,将变量声明作为GO对象的属性名,值为undefined  		
	3. 在函数体里面找函数声明,值赋予函数体
	注意:定义的变量声明以及函数名如果相同,也只能作为GO对象的一个属性名(对象属性的唯一性)
				
  • 举个例子,来详解全局预编译三部曲
    var a = 10        
    function a() {}
    console.log(a)
	// 第一步  创建GO对象
     GO {      
     }

    // 第二步 找变量声明,将变量声明作为GO对象的属性名,值为undefined  
    GO {
      a: undefined
      //...还有其他内容,原型链会讲
    }
    // 第三步 在函数体里面找函数声明,值赋予函数体
    GO {
      a: function a() {}
      //...还有其他内容,原型链会讲
    }
    // 到此预编译完成,开始从上到下依次执行代码
    var a = 10     =>   a: function a() {} =>  a: 10 
    function a() {}  =>  经过上一步,a已经指向10,所以这个函数变成无效代码,无法调用 
    console.log(a)  =>  10

二.作用域[[scope]] (暂时不涉及es6)

  • 作用域[[scope]]: [[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。即作用域决定了代码区块中变量和其他资源的可见性。
  • 作用域分全局作用域和局部(函数)作用域
	// 全局作用域
    function a() {
    	var b = 10
    }
    var glod = 100
    console.log(b) // 报错 b is not defined(b没有定义) 原因是[[scope]]中并没有属性b 

在这里插入图片描述

三.作用域链

  • 作用域链: [[scope]]中所储存的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫作用域链
  • 查找变量: 作用域链的顶部依次向下查找
    function a() {
      function b() {
        var b = 234;
      }
      var a = 123;
      b();
    }
    var glod = 100
    a()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四.闭包

  1. 闭包的概念:当内部函数被保存到外部,将生成闭包. 本质上,闭包是将函数内部和函数外部连接起来的桥梁。

  2. 注意:每个函数执行完毕就销毁作用域链,闭包会导致原有作用域链不释放造成内存泄露.(内存泄露指的是内容被占用,内容变小)

    function a() {
      var b = 100
      function c() {
        console.log(b) 
      }
      return c
    }
    console.log(a()())  // 打印 100
    这时我们在a函数外部依然读取到a函数中定义的变量b,这个就是闭包
    
    这个函数中闭包导致的内存泄露: 原本a函数指向完就销毁他的执行期上下文,
    但是现在a的执行期上下文中的b属性仍然被c函数使用,所以无法销毁,导致多
    占用了内存,这个就是内存泄露.
	

3.闭包的应用场景:

  • 变量私有化
  • 柯里化
  • 函数防抖
  • 函数节流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值