1.立即执行函数

IIFE => immediately invoked function expression

  1. 自动执行,执行完成之后立即释放.
  2. 立即执行函数 => 初始化函数

    1.1 写法

    ```javascript 写法1: (function(){ })()

写法2: w3c推荐写法 (function(){ }())

  1. <a name="YhNDf"></a>
  2. ### ()包起来的,都是表达式,一定是表达式才能被执行
  3. ```javascript
  4. (function(){
  5. console.log(可以立即执行);
  6. })()
  7. function(){
  8. }()
  9. => 理解成
  10. function(){}
  11. () 并不会立即执行
  12. // 可以被执行,
  13. var test = function(){
  14. console.log(2);
  15. }()
  16. console.log(test); // undefined

1.2 可以携带参数

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

1.3 立即执行函数的返回值

  1. var test = (function(a, b){
  2. return a + b
  3. })(2, 3)
  4. console.log(test); // 5
  5. var name = (function(name){
  6. return name
  7. })('bobo')
  8. console.log(name); // bobo

1.4 函数可以立即执行的情况

  1. 1. 第一种
  2. (function(){
  3. console.log(1);
  4. })()
  5. 2. 第二种
  6. var test = fucntion(){
  7. console.log(1);
  8. }() // 可以执行,因为()之前为表达式
  9. 3.第三种
  10. function test(){
  11. console.log(1);
  12. }() // 会报错
  13. !() 内部不写, 会报错
  14. function test(){
  15. }('1') 传入会被当表达式,不会报错,不会执行

1.5 立即执行函数立即执行结束后,就会被销毁

  1. var test = (function(){
  2. console.log(1); // 1
  3. })()
  4. console.log(test);// undefined
  5. // 打印 1 和 undefined 证明立即执行函数执行结束之后,立即被销毁了,
  6. // 所以test是undefined

1.6 立即执行函数的函数名无意义,会自动被忽略,

  1. var a = 10;
  2. if(function b(){}){
  3. a += typeof(b);
  4. }
  5. console.log(a); // '10undefined'

1.7 把函数声明变成表达式的方法 + - ! || && void

image.png

  1. +function(){
  2. console.log(1);
  3. }() // 1
  4. -function(){
  5. console.log(1);
  6. }() // 1
  7. !function(){
  8. console.log(1);
  9. }() // 1
  10. 0 || function(){ // 隐式转换成fasle的都可以 undefined null false 0 ''
  11. console.log(1);
  12. }() // 1
  13. 1 && function(){ //隐式转换不是false的都可以
  14. console.log(1);
  15. }() // 1
  16. void function(){
  17. console.log(1);
  18. }() // 1
  19. 2, 3, function(){
  20. console.log(1);
  21. }() // 1

2. ,逗号运算符

对它的每个操做数求值,从左到右,返回最后的值。

  1. var num = (2, 3, 45, 767);
  2. console.log(num);// 767

3.闭包深入

案例1: 打印0-9

  1. function test() {
  2. var arr = [];
  3. for(var i = 0; i < 10; i++) {
  4. arr[i] = function() {
  5. document.write(i + '');
  6. }
  7. }
  8. return arr;
  9. }
  10. var myArr = test();
  11. for(var j = 0; j < 10; j++) {
  12. myArr[j]();
  13. } // 打印10个10
  14. // 方法1 => 立即执行函数
  15. function test() {
  16. for(var i = 0; i < 10; i++) {
  17. (function() {
  18. document.write(i + '');
  19. })()
  20. }
  21. }
  22. test();
  23. // 方法2 在外边传入参数
  24. function test() {
  25. var arr = [];
  26. for(var i = 0; i < 10; i++) {
  27. arr[i] = function(num) {
  28. document.write(num + '');
  29. }
  30. }
  31. return arr;
  32. }
  33. var myArr = test();
  34. for(var j = 0; j < 10; j++) {
  35. myArr[j](j);
  36. }
  37. // 方法3 将其在函数内部进行保存
  38. function test() {
  39. var arr = [];
  40. for(var i = 0; i < 10; i++) {
  41. (function(j){
  42. arr[j] = function(j){
  43. document.write(j + ' ');
  44. }
  45. })(i)
  46. }
  47. return arr;
  48. }
  49. var myArr = test();
  50. for(var j = 0; j < 10; j++) {
  51. myArr[j]();
  52. }

案例2: 点击事件打印

  1. <ul>
  2. <li>1</li>
  3. <li>2</li>
  4. <li>3</li>
  5. <li>4</li>
  6. <li>5</li>
  7. </ul>
  8. <script type="text/javascript">
  9. var oLi = document.querySelectorAll('li');
  10. console.log(oLi);
  11. for(var i = 0; i < oLi.length; i++){
  12. (function(j){
  13. oLi[j].onclick = function(){
  14. console.log(j);
  15. }
  16. })(i)
  17. }
  18. </script>

4.面试

  1. function test(a){
  2. console.log(a);// 不会执行
  3. }(6) // (6) 被当成了表达式,而不是立即执行符号
  4. test(1);// 打印输出 1
  1. var fn = (
  2. function test1(){
  3. return 1
  4. },
  5. function test2(){
  6. return '2'
  7. }
  8. )();
  9. console.log(fn);// '2'
  10. console.log(typeof(fn));// string
  1. var a = 10;
  2. // ! (function b(){}) => 表达式,函数名称被忽略, => undefined
  3. if(function b(){}){
  4. a += typeof(b);
  5. }
  6. console.log(a); // 10undefined

5.练习

1. 累加器,初始值为0,写个闭包,执行一次函数加1打印

  1. function accu(){
  2. var i = 0;
  3. return function add(){
  4. // i++;
  5. // console.log(i);
  6. console.log(++i);
  7. }
  8. }
  9. var accu1 = accu();
  10. accu1();
  11. accu1();
  12. accu1();

2. 缓存器:

缓存器 : 一个班级,学生名保存在一个数组,俩个方法写在函数中的一个对象中,
第一个方法,加入班级,第二个方法离开班级
每次加入或离开,都需要打印新的学生名单

  1. function buffer(){
  2. var studentsArr = ['小明','小红'];
  3. var operStd = {
  4. join:function(name){
  5. studentsArr.push(name);
  6. console.log(studentsArr);
  7. // for(var i = 0; i < studentsArr.length; i++){
  8. // (function(){
  9. // console.log(studentsArr[i]);
  10. // })()
  11. // }
  12. },
  13. quit: function(name){
  14. var index = studentsArr.indexOf(name);
  15. // console.log(index);
  16. if(index !== -1){
  17. studentsArr.splice(index,1);
  18. }
  19. console.log(studentsArr);
  20. // for(var i = 0; i < studentsArr.length; i++){
  21. // var item = studentsArr[i]; // ? for循环型性能 的优化
  22. // if(item === name){
  23. // studentsArr.splice(i);
  24. // }
  25. // }
  26. }
  27. };
  28. return operStd
  29. }
  30. var operStd = buffer();
  31. operStd.join('小阿飞');
  32. operStd.quit('小红');