作用域和闭包初识

一、预编译

  • 如果变量未经声明就赋值,此变量为全局对象所有。 a = 10; --> window.a = 10;
  • 一切声明的全局变量,全部是window的属性 .var b = 243; --> window.b = 243;
  • 预编译发生在函数执行的前一刻
    四部曲:
  1. 先创建AO对象
  2. 找形参和变量声明,将变量和形参作为AO属性名,值为undefined
  3. 实参形参统一
  4. 函数体中找函数声明,值赋为函数体

eg

      function fn(a) {
         console.log(a); //function a () {}
         console.log(b);// undefined
         
         var a = 123;
         console.log(a); //123
         
         function a() {}
         console.log(a); //123
         
         var b = function () {}
         console.log(b); //function () {}
         
         function d() {}
     }
     fn(1);
   //预编译过程
  // 1. 创建AO对象
  // 2. AO{
  //     a : undefined
  //     b : undefined
  //  }
  // 3. AO{
  //      a : 1
  //      b : undefined
  //  }
  // 4.AO{
  //      a : function a () {}
  //      b : undefined
  //      d : function d () {}
  //之后开始执行函数

在这里插入图片描述

做一道题,先找GO(全局的) , 再找AO(自己的)

二、作用域

  1. 执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象,函数执行就会产生执行期上下文(独一无二的),执行完一次会销毁一次。
  2. [[scope]]:存储作用域执行期上下文的集合。

三、作用域链

  1. [[scope]]中所存储法人执行期上下文对象的集合,这个集合呈链式连接,我们把这种链式连接叫做作用域链。作用域链先将自己的AO放在第0位,然后才是GO。
  2. 查找变量:在哪个函数里面查找变量,就在这个函数的作用域链的顶端依次向下查找。

举个栗子

function a(){
   function b(){
      var b = 234;
   }
   var a = 123;
   b();
}
 var glob = 100;
 a();

刚开始的时候a被定义
在这里插入图片描述
此时a要被执行
在这里插入图片描述

b在开始时就在a的AO中
在这里插入图片描述
b在执行时会产生一个属于自己的AO,放在作用域链最顶端 0位。
在这里插入图片描述

四、闭包初识

  1. 当内部函数被保存到外部时,将会生成闭包
  2. 闭包会导致原有作用域链不释放,造成内存泄漏。

闭包的作用

  • 实现共有变量,eg:累加器
  • 可以做缓存(存储结构)
  • 可以实现封装,属性私有化
  • 模块开发,防止污染全局变量
    function a() {
        function b() {
            var bbb = 234;
            document.write(aaa);
        }
        var aaa = 124;
        return b;//形成闭包,执行之后销毁a的 AO,但是b的没有被销毁
    }
    var glob = 100;
    var demo = a();//此时存的是b
    demo();//124

首先当a定义
在这里插入图片描述

a执行完之后,把b存到外部了,a的AO被销毁,但是b还存着A的AO
在这里插入图片描述

此时执行demo也就是执行b,找第0位,自己的AO中没有aaa,找第一位,也就是之前a的AO,其中的aaa = 124,访问这个aaa。

1.累加器

    function test() {
        var num = 100;
        function a (){
            num ++;
            console.log(num);
        }
        function b () {
            num --;
            console.log(num);
        }
        return [a,b];//a,b都和test产生闭包,一对二的关系

    }
    var myArr = test();
    myArr[0]();//101
    myArr[1]();//100,在前一个AO的基础上减,因为共用一个test产生的AO

具体讲解如下
在这里插入图片描述


2.缓存

     function eater() {
        var food = "";//作为存储结构来用
        var obj = {
            eat : function () {
                console.log("I am eating " + food );
                food = "";
                
            },
            push : function (myFood) {
                food = myFood;
            }
        }
        return obj;
    }
    var eater1 = eater();
    eater1.push('banana');
    eater1.eat();//I am eating banana

五、立即执行函数

执行完就被释放,其余和函数一样

基本结构

 1.(function (){
     中间写代码
   }()) //建议使用第一种
  
 2.(function (){
     中间写代码
   })()

eg

 (function abc (){
   var a = 123;
   var b = 234;
   console.log(a + b); //357
 }())
 //执行一次之后访问abc会报错,被销毁了

只有表达式才能被执行

 function test(){
    var a = 123;
 }() //这种不能被执行,这个叫函数声明

能被执行符合执行的表达式的函数名会被自动忽略

 var test = function (){
    console.log('a');
 }(); //可以执行,再次访问test,返回undefined

立即执行函数举例

    var num = (function (a,b) {
        var d = a + b;
        return d;//3
    }(1,2));

下次将深层次讲解闭包和对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值