• js函数、作用域、作用域链、闭包、立即执行函数


    1.函数

    定义

    1.函数声明

    function test(){
    函数体
    };

    2.函数表达式:
    - 命名函数表达式 
    - ```java
    var fn = function test(){};
    
    • (匿名)函数表达式

    var fn = function(){};

    
    #### 组成形式
    1.函数名称
    2.参数(形参、实参)
    3.返回值
    
    ### 2.作用域
    1. 作用域定义:变量(变量作用域又称上下文)和函数生效的区域。
    2. [[scope]]:每个js函数都是一个对象,对象中的属性有些我们可以访问,有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个,[[scope]]存取了运行期上下文的集合。
    3. 作用域链:[[scope]]中锁存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接成为作用域链。
    4. 执行期上下文:当函数执行时,会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行器上下文都是独一无二的,
      所以多次调用函数就会创建多个执行器上下文,当函数执行完毕,它所产生的执行期上下文会被销毁。 5. 查找变量:从作用域链顶端向下查找。 ### 3.闭包 1. 定义:当内部函数被保存到外部时,将会生成闭包。闭包将会导致作用域链不释放内存,导致内存泄露。 ```java function a(){ function b(){ } return b;//保存到外部 } var demo = a(); demo(); demo(); //a()执行的时候,会定义b,b是在a执行的时候定义,定义的时候会在aAO -- > GO,并且a执行后返回b,b被保存到外部,故这个之后aAO不会被释放,从而造成内存泄露。
    1. 闭包的作用
    • 实现公有变量
      • eg: 函数累加器
      function add(){
        var count = 0;
        function demo(){
          count++;
          console.log(count);
        }
        return demo;
      }
      var counter = add();
      counter();
      counter();
      counter();
      
    • 可以做缓存(存储结构)
      多个函数被保存为一个函数的闭包,它们操作的是同一块内存。
      • 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]();//101
      myArr[1]();//100
      
      function eater(){
        var food = "apple";
        var obj = {
          eatFood: function () {
            if(food != ""){
              console.log("eating "  + food);
              food = '';
            }else{
      	  	console.log("it is empty.")
      	  }
          },
          pushFood: function (myfood) {
            food = myfood;
          }
        }
        return obj;
      }
      
      var person = eater();
      person.eatFood();//eating apple
      person.pushFood("banana");
      person.eatFood();//eating banana
      
    - 可以实现封装,属性私有化
    	- eg:Person()
    - 模块化开发,防止污染全局变量
    
    ### 4. 立即执行函数
    针对初始化功能的函数
    立即执行函数执行完就被销毁。
    ```java
    var num = (function (a,b,c){
    	var d = a+b+c;
    	return d;
    }(1,2,3));
    

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

    var test = function(){};
    test();//表达式,可以被执行。
    
    + function (){
    	console.log('a');
    }();//可以执行,前面加的+让它变成了表达式。加-也一样的道理。
    
    function test(){
    	var arr = [];
    	for(var i = 0;i <10;i++){
    		arr[i] = function(){
    			document.write(i+" ");
    		}
    	}
    	return arr;
    }
    var myarr = test();
    for(var j = 0;j < 10;+j+){
    	myarr[j]();
    }//10 10 10 10 10 10 10 10 10 10 
    //arr里面存的十个元素都是函数体,返回arr后被保存到外部,形成闭包,当myarr = test()执行的时候,arr里面存了十个函数体,最后退出test的时候i=10.当执行myarr[j]的时候,
    运用的是test()的执行期上下文,而test()退出时,testAO里面的i=10.故输出了10个10. function test(){ var arr = []; for(var i = 0;i <10;i++){ (function (j){ arr[j] = function() { document.write(j+" "); } }(i)); } return arr; } var myarr = test(); for(var j = 0;j < 10;j++){ myarr[j](); }//0 1 2 3 4 5 6 7 8 9
     
  • 相关阅读:
    随机验证码生成
    python之map和filter
    Json学习笔记
    动态规划求区间最值问题RMQ(Range Minimum/Maximum Query)
    积水问题
    5亿个数找中位数
    Linux下进程间通信:命名管道mkfifo
    Trie树总结
    树的公共祖先问题LCA
    类文件结构
  • 原文地址:https://www.cnblogs.com/1549983239yifeng/p/14431213.html
Copyright © 2020-2023  润新知