美文网首页
函数表达式、匿名函数、闭包

函数表达式、匿名函数、闭包

作者: 艾石溪 | 来源:发表于2016-12-04 18:30 被阅读58次

    这两天看这个理论知识,看的有点小恶心了。。现在稍微总结一下,大体知道的,然后不全的再随着自己的理解往上加。

    函数表达式

    • 什么是函数表达式?
      定义函数有两种方式,一个是函数声明,另一个是函数表达式。函数声明最重要的一个特征是函数声明提升。
      函数声明:

      function functionName(arg0, arg1, arg2){
          //函数体
      }
      

    函数表达式:

        var functionName = function(arg0, arg1, arg2) {
            //函数体
        }
    
    • 为啥会出现函数表达式?
      既然函数声明比较好理解,同时还具有函数声明提升的特征,为啥要出现函数表达式??
      原因一:

      if(condition) {
          function sayHi( ){
              alert(" Hi ! ");
          }
      }else{
          function sayHi( ){
              alert(" Yo ! ");
          }
      }
      

    其实上面代码的本意是很清楚的,希望能根据不同的condition可以执行不同的部分。但是,函数声明提升会导致语法错误,而各个浏览器修复错误的方式是不同的,所以执行结果也会不同。这个时候,函数表达式可以解决这个问题。

        if(condition) {
            sayHi = function ( ){
                alert(" Hi ! ");
            }
        }else{
             sayHi function ( ){
                alert(" Yo ! ");
            }
        }
    

    原因二:
    javascript中没有块级作用域的概念,可以使用函数表达式、匿名函数来模拟实现这个功能。

    var someFunction = function( ) {
        //这里是块级作用域
    };
    someFunction( );
    

    同时在这里说一下“立即执行函数表达式”,常见的几种方式包括
    (1)

    ( function ( ){
        console.log(" test ! ");
    })( );
    

    (2)

    ( function ( ){
        console.log(" test ! ");
    }( ));
    

    以上是正确的“立即执行函数表达式”的正确写法。可能很多人会有疑问,为什么要这样子写??

    function ( ){ }( );      //出错
    

    当像上面这样写的时候,会出现语法错误,因为javascript当遇到function关键字时,会当作函数声明的开始,而函数声明后面跟的应该是函数名,而不能是圆括号,所以会出现语法错误。那为啥上面两种方法就可以实现“立即执行”的功能,不报错呢。因为javascipt中语法中,()里面会自动解析成表达式,而不是语句。比如:

     / / 如果传入字面量(literal),则返回表达式(expression)
    (1) // 1
    (function(){console.log("f");}) // function () {console.log("f")}
    

    通过上面的描述应该大概懂了一些,那如何实现模拟块级作用域的呢。

     //a.js 
    var num = 1;
    // code....
    
     //b.js 
    var num = 2;
    // code....
    

    当同时引入a.js、b.js时,一定会造成num变量的覆盖,为了解决这个问题,我们的“立即执行函数表达式”就发挥作用了呢。
    a.js

     (function(){
        var num = 1;
        // code....
     })();
    

    b.js

     (function(){
        var num = 1;
        // code....
     })();
    

    经过改造之后,现在两个库成为完全独立的了,就可以放心大胆的使用了。

    匿名函数:顾名思义,就是没有名字的函数。

    匿名函数的用途之一就是把函数当成值来使用。

    闭包

    • 啥是闭包?
      闭包就是能够读取其它函数内部变量的函数。是将函数内部和函数外部连接起来的一座桥梁。

    • 闭包的用处??
      为啥会出现闭包呢,因为javascript作用域链的作用,函数内部可以访问函数外部的作用域,但是外部想访问内部的变量就不可以了。闭包的最大用处有2个,一个是可以读取函数内部的变量,另一个就是可以让这些变量的值始终保持在内存中。

    • 闭包经常出现的问题

      function createFunctions(){
          var result = new Array();
      
          for(var i = 0; i < 10; i++){
              result[i] = function(){
                  return i;
              };
          }
          return result;
      }
      

    上面代码返回的数组,每个函数都返回的是10。因为每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以它们引用都是同一个变量i。我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。

        function createFunctions(){
            var result = new Array();
    
            for(var i = 0; i < 10; i++){
                result[i] = function(num){
                    return function(){
                        return num;
                    };
                }(i);
            }
            return result;
        }
    
    • 闭包用来模拟单例

      var counter = (function(){
      var i = 0;
      return {
          get: function(){
              return i;
          },
          set: function( val ){
              i = val;
          },
          increment: function() {
              return ++i;
          }
       };
      }());
      
      counter.get(); // 0
      counter.set( 3 );
      counter.increment(); // 4
      counter.increment(); // 5

    相关文章

      网友评论

          本文标题:函数表达式、匿名函数、闭包

          本文链接:https://www.haomeiwen.com/subject/zjlqmttx.html