zoukankan      html  css  js  c++  java
  • 立即执行函数和使用场景

    一、什么是立即执行函数?

    声明一个函数,并马上调用这个匿名函数就叫做立即执行函数;也可以说立即执行函数是一种语法,让你的函数在定义以后立即执行;

    立即执行函数的创建步骤,看下图:

    二、立即执行函数的写法:

    有时,我们定义函数之后,立即调用该函数,这时不能在函数的定义后面直接加圆括号,这会产生语法错误。产生语法错误的原因是,function 这个关键字,既可以当做语句,也可以当做表达式,比如下边:

    //语句
    function fn() {};
    
    //表达式
    var fn = function (){};
    为了避免解析上的歧义,JS引擎规定,如果function出现在行首,一律解析成语句。因此JS引擎看到行首是function关键字以后,认为这一段都是函数定义,不应该以原括号结尾,所以就报错了。
    解决方法就是不要让function出现在行首,让JS引擎将其理解为一个表达式,最简单的处理就是将其放在一个圆括号里,比如下边:
    (function(){
    //code
    }())
    
    (function (){
    //code
    })()
    上边的两种写法,都是以圆括号开头,引擎会意味后面跟的是表达式,而不是一个函数定义语句,所以就避免了错误,这就叫做"立即调用的函数表达式"。
    立即执行函数,还有一些其他的写法(加一些小东西,不让解析成语句就可以),比如下边:
    (function () {alert("我是匿名函数")}())   //用括号把整个表达式包起来
    (function () {alert("我是匿名函数")})()  //用括号把函数包起来
    !function () {alert("我是匿名函数")}()  //求反,我们不在意值是多少,只想通过语法检查
    +function () {alert("我是匿名函数")}() 
    -function () {alert("我是匿名函数")}() 
    ~function () {alert("我是匿名函数")}() 
    void function () {alert("我是匿名函数")}() 
    new function () {alert("我是匿名函数")}() 

    三、立即执行函数的作用:

    • 不必为函数命名,避免了污染全局变量
    • 立即执行函数内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
    • 封装变量
    总而言之:立即执行函数会形成一个单独的作用域,我们可以封装一些临时变量或者局部变量,避免污染全局变量

    四、使用场景

    1.怎样使以下alert的结果为0,1,2:

    <body>
        <ul id="list">
            <li>公司简介</li>
            <li>联系我们</li>
            <li>营销网络</li>
        </ul>
        <script>
           var list = document.getElementById("list");
          var li = list.children;
          for(var i = 0 ;i<li.length;i++){
            li[i].onclick=function(){
              alert(i);  // 结果总是3.而不是0,1,2
            }
          }
         </script>  
    </body>
    为什么alert总是3? 因为i是贯穿整个作用域的,而不是给每一个li分配一个i,点击事件使异步,用户一定是在for运行完了以后,才点击,此时i已经变成3了。
    那么怎么解决这个问题呢,可以用立即执行函数,给每个li创建一个独立的作用域,在立即执行函数执行的时候,i的值从0到2,对应三个立即执行函数,这3个立即执行函数里边的j分别是0,1,2所以就能正常输出了,看下边例子:
    <body>
        <ul id="list">
            <li>公司简介</li>
            <li>联系我们</li>
            <li>营销网络</li>
        </ul>
        <script>
           var list = document.getElementById("list");
          var li = list.children;
          for(var i = 0 ;i<li.length;i++){
           ( function(j){
                li[j].onclick = function(){
                  alert(j);
              })(i); //把实参i赋值给形参j
            }
          }
         </script>  
    </body>

    当然,也可以使用ES6的块级作用域解决整个问题:

    <body>
        <ul id="list">
            <li>公司简介</li>
            <li>联系我们</li>
            <li>营销网络</li>
        </ul>
        <script>
          var list = document.getElementById("list");
          var li = list.children;
          for(let i = 0 ;i<li.length;i++){
            li[i].onclick=function(){
              alert(i);  // 结果是0,1,2
            }
          }
         </script>  
    </body>

    2.如何避免了污染全局变量

    某些代码只需要执行一次,比如只需要显示一个时间,但是这些代码也需要一些临时的变量,但是初始化过程结束之后,就再也不会被用到,如果将这些变量作为全局变量,不是一个好的主意,我们可以用立即执行函数——去将我们所有的代码包裹在它的局部作用域中,不会让任何变量泄露成全局变量,看如下代码:

    比如上面的代码,如果没有被包裹在立即执行函数中,而是直接以非函数的形式直接写在<script>标签里面,虽然也会立即执行,但是临时变量todaydom,days,today,year,month,date,day,msg都将成为全局变量(初始化代码遗留的产物)。
    而用立即执行函数之后,这些变量都不会在全局变量中存在,以后也不会其他地方使用,有效的避免了污染全局变量。
    转自:https://www.jianshu.com/p/b10b6e93ddec
     
  • 相关阅读:
    pixysoft.framework.messageflow enterprise edition 开发实录
    软件工程革命三部曲 — 系统开发分类与重用说明
    vs2010 premium版本 使用小结 更多是问题。。
    报表引擎终于做出来了!!!
    报表引擎终于做出来了!!!!!参考了根兄的文档。
    页面驱动开发(Page Driven) —— 一种大多数人还不认同的技术
    从SOA到云计算 我个人理解
    谈谈Exception,什么时候抛出?什么时候接住? 二
    软件工程革命三部曲 —— 系统开发的业务部分重构在思考。
    Pixysoft.Framework.Reports 开发实录
  • 原文地址:https://www.cnblogs.com/q582141490/p/13560747.html
Copyright © 2011-2022 走看看