闭包上+立即执行函数

232 阅读4分钟

1、闭包的定义:闭包就是能够读取其他函数内部变量的函数。在js中,可以将闭包理解成“函数中的函数。

但凡是内部的函数被保存到了外部,生成闭包。内部函数会保存外部函数的成果。闭包会导致原有作用域链不释放,造成内存泄漏(过多占用内存资源)

例子1

function a(){
    function b() {
        var bbb = 234;
        console.log(aaa);
    }
    var aaa = 123;
    return b;//里面的函数b被保存到了外面
}

var glob = 100;
var demo = a();//a执行的结果---b
demo();

例子2

function a(){

    var num = 100;
    function b (){
        num ++;
        console.log(num);
    }
    return b;//把b扔到demo里面去,b()是a的最后一条语句被执行完a函数就被执行完了,
    //b在这里拿到了a的执行期上下文
    //如果b在这里就执行,b(),那么生成不了闭包
}
var demo = a();//demo()和b()是一样的,名称不同
demo();//101
demo();//102
第一次aAO {num : 101}----
闭包的作用
1、实现公有变量------eg: 函数累加器

例子

function add(){
    var count = 0;
    function demo(){
        count++;
        console.log(count);
    }
    return demo;
}
var counter = add();//add执行结果demo
counter();
counter();
counter();
counter();
counter();
counter();
----------打印123456
2、可以做缓存(存储结构)----eg:eater

例子

function test(){
    var num = 100;
    function a(){
        num ++;
        console.log(num);
    }
    function b(){
        num --;
        console.log(num);
    }
    return[a,b];
}
var myArr = test();
myArr[0]();//函数a===101
// a doing     a.[[scope]]  0 : aAO
                         // 1 : testAO
                         // 2 : GO
myArr[1]();//函数b===100  //a,b是并集,共用一个test的AO,-----有执行顺序
b doing     b.[[scope]]  0 : aAO
                         1 : testAO (是a执行后改变过值基础上再操作的)
                         2 : GO

例子

  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();

// 例子2

function test(){
      var food = "apple";
      var obj = {
          eatFood : function(){
              if(food != ""){
              console.log("i am eating " + food);
              food = "";
            }   else{
              console.log("There is empty!")
            }
      },
          pushFood : function(myFood) {
              food = myFood;
          }
      }
      return obj;
  }
  var person = test();
  
  person.eatFood();
  person.eatFood();
  person.pushFood("banana");
  person.eatFood();
3、可以实现封装,属性私有化----eg:Person();
4、模块化开发,防止污染全局变量

立即执行函数

(只想执行一次,和函数其余的地方都一样,除了执行完立即被销毁,释放内存) 针对初始化功能的函数

别人的总结:(函数表达式后加上()可以被直接调用,但是把整个声明式函数用()包起来的话,则会被编译器认为是函数表达式,从而可以用()来直接调用,如(function test(){...})(),

但是如果这个括号加在声明式函数后面,如function test(){...}(),则会报错,不符合js的语法,所以想要通过浏览器的语法检查,就必须加点符号,比如()、+、!等)

表达式1:(function(){}() );建议这种
表达式2:(function(){}) ();

例子1

(function abc(a,b,c){
    var a = 123;
    var b = 234;
    console.log(a + b +c*2);
}(1,2,3))

立即执行函数 2021-05-29 223513.jpg

例子1

var num = (function(a,b,c){//num=7
    var d = a + b + c*2 - 2;
    return d;//有返回值
}(1,2,3));///num=7

只有表达式才能被执行符号执行

// (function test(){})函数声明被包起来变成了函数表达式,就可以被执行了,//大括号是执行符

例子1

function test(){
    var a = 123;
}
test();------------test()就是一个表达式,可以调用函数

例子2

var test = function(){
    console.log("a");
}()//-------------**函数表达式可以被执行**var test调用函数

例子3-----只有函数声明,不能执行

function test(){
    var a = 123;
}() //--------------**函数声明,不能执行**

能被执行符号()执行的表达式函数名字就会被自动忽略

例子4

var test = function(){
    console.log("a");
}();//加上执行符号的(test:undefined)表达式自动放弃函数名称,成了立即执行函数

执行符号执行的表达式224643.jpg

//这里test=undefined,取决于后面的值类型,等号=后面是一个表达式,前面的是变量声明,在执行时会放弃函数储存到test里面的引用,让test回归到被声明的状态

例子5--//加上+号/负号-/!算可执行表达式,转化成数字,被执行但乘号*和➗/不行

 + function test(){
    console.log("a");
}();

test 2021-05-29 224950.jpg

例子

(function (){
    console.log("a");
}())//括号是执行符,先执行最外面的括号,只有外面是数学运算的小括号,里面的括号有语法意义,把里面变成表达式,被里面执行

例子

function test(a,b,c,d) {
    console.log(a+b+c+d);
}(1,2,3,4)//执行符号里面有东西就不是执行符号,而是分开,逗号,也算语法,不报错,不执行



(1,2,3,4)//系统理解在下面