我们在之前写的函数声明在全局环境下是不会被释放的,始终存在于GO中,可以随时随地的调用。

  1. // 每次页面加载求数据的和,都需要调用一次。
  2. add(1, 2);
  3. function add(a, b) {
  4. console.log(a + b);
  5. }

那么有没有一种函数是可以自己执行且执行完成会立即被释放的函数呢?

立即执行函数初识

「立即执行函数」IIFE(immediaely invoked function expression)

立即执行函数的特点就是:不需要手动调用自动立即执行,执行完成后立即销毁

  1. // 写法一
  2. (function(){
  3. // 执行内容
  4. })()
  5. // 写法二,W3C 推荐的写法
  6. (function(){
  7. // 执行内容
  8. }())

以上两种写的区别只是()()里外的区别!!!而多数开发人员的习惯倾向于第一种写法。

立即执行函数传参:

  1. (function(a,b){
  2. console.log(a+b); // 3
  3. })(1,2)

立即执行函数返回值:

  1. var num = (function(a,b){
  2. return a+b;
  3. })(1,2)
  4. console.log(num); // 3

立即执行函数会忽略函数名:

  1. (function test() {
  2. var a = 2;
  3. var b = 2;
  4. console.log(a + b);
  5. })();
  6. console.log(test); // error

以上代码在立即执行函数执行后打印函数名会提示报错,这也进一步说明了立即执行函数执行完会释放的定论。

立即执行函数 & 表达式

函数只有是表达式的时候才能被执行符号**()**执行。 :::info 用()包裹起来的函数就是函数表达式!!! :::

  1. function test1(){}(); // 不会执行且报错
  2. var test2 = function(){}(); // 执行,因为这个本来就是函数表达式声明
  3. (function test3(){})(); // 执行

立即执行函数执行且销毁:

  1. var test = function(){}();
  2. console.log(test); // undefind,test 函数被销毁

函数表达式的函数名会被忽略:

  1. (function test() {
  2. console.log(123);
  3. })();
  4. console.log(test); // error

这里又可以插入一道面试题了🛋 :

  1. // 请问 a 打印什么?
  2. var a = 10;
  3. if (function b() {}) {
  4. a += typeof b;
  5. }
  6. console.log(a);
  7. /**
  8. * 答案是 10undeind
  9. * 因为在 if 判断中JS引擎将 (function b(){}) 立即为函数表达式
  10. * 函数表达式是忽略函数名的
  11. * 所以 typeof b 返回 undefind
  12. * 结果是 10undefind
  13. */

使用+、-、!、&&、||都能将函数声明转换成函数表达式:

  1. +function test(){
  2. console.log(1); // 1
  3. }()
  4. ||function test(){
  5. console.log(1); // 1
  6. }()

下面插入一道面试题 🌴 :

  1. // 以下代码能正常执行吗?
  2. function test(a,b) {
  3. console.log(a,b)
  4. }(6,7);
  5. // 其实是完全可以的,但是不会执行 test 函数
  6. // 当函数声明直接使用()进行执行的时候,这样函数会被认为是一个立即执行函数,这样会直接显示语法错误
  7. // 当时这里的(6,7)是会被解释成逗号运算符的,JS引擎会将以上代码解释为
  8. function test(){};
  9. (6,5);

逗号运算符

逗号运算符永远返回(),的最后一项数据。

  1. console.log((1,2)); // 2
  2. console.log((2 - 1, 6 + 5, 24 + 1)); // 25

结合立即执行函数在看一道面试题🔑 :

  1. // 问打印什么?
  2. var fn =
  3. (function test1() {
  4. return 1;
  5. },
  6. function test2() {
  7. return 2;
  8. })();
  9. console.log(typeof fn); // number
  10. /**
  11. * 打印 number
  12. * 因为逗号运算符返回()中最后一个数据,也就是 test2
  13. * (function test2(){})() 形成了立即执行函数,返回 2
  14. * 所以打印 number
  15. */

立即执行函数 & 闭包问题

闭包的问题就是函数内部的变量可以被外部操作,这里有道经典的闭包面试题可以配合立即执行函数来解题:

  1. // 请问 document.write 会输出什么???
  2. function test() {
  3. var arr = [];
  4. for (var i = 0; i < 10; i++) {
  5. arr[i] = function () {
  6. document.write(i + " ");
  7. };
  8. }
  9. return arr;
  10. }
  11. var myArr = test();
  12. for (var index = 0; index < myArr.length; index++) {
  13. myArr[index]();
  14. }
  15. /**
  16. * 答案是 10 10 10 10 10 10 10 10 10 10
  17. * 那为什么是 10 个 10 呢?这就是因为闭包导致的,我们将 test 函数进行分解
  18. * 首先在 for 循环中保存了 10 个 function, 但是这 10 个 function 并没有执行,而是在外面的 myArr 执行,这样就形成了闭包
  19. * 当 myArr 执行每一个函数的时候,每个函数在回头去找 test 中的 i,此时的 i 已经变成了 10,所以 打印出 10 个 10
  20. 将 for 循环进行拆分
  21. var i = 0;
  22. for(; i < 10; ){
  23. arr[i] = function () {
  24. 查找 i ,发现 i 已经变成了 10
  25. document.write(i + " ");
  26. };
  27. i++
  28. }
  29. */
  30. // 如何解决呢?
  31. // 我们可以用立即执行函数形成一个独立的函数
  32. // 这样就可以解决了
  33. function test() {
  34. var arr = [];
  35. for (var i = 0; i < 10; i++) {
  36. // 保存一个独立的作用域
  37. (function (j) {
  38. arr[j] = function () {
  39. // 打印的是立即执行函数的参数
  40. document.write(j + " ");
  41. };
  42. })(i);
  43. }
  44. return arr;
  45. }
  46. var myArr = test();
  47. for (var index = 0; index < myArr.length; index++) {
  48. myArr[index]();
  49. }