立即执行函数,闭包函数

一. 立即执行函数

1. 概念

声明一个函数,并马上调用这个匿名函数就叫做立即执行函数。

2. 立即执行函数的作用

1. 不必为函数命名,避免了污染全局变量。( 什么叫全局变量污染:就是直接给window添加属性和方法,污染全局变量的后果就是,在多人开发中,容易造成命名的冲突)

2. 立即执行函数内部形成了一个独立的作用域,可以封装一些外部无法读取的私有变量。这个作用域里面的变量,外面访问不到,这样就可以避免变量污染。

3. 闭包和私有数据 

//立即执行函数的两种写法

//第一种:用括号把整个函数定义和调用包裹起来
(function(){
 //function body
}())

//第二种:用括号把函数定义包裹起来,后面再加括号
(function (){
 //function body
})()

通常,看到这样的代码,会觉得这样的执行效果是点击第一个li,则会输出1,点击第二个li,则会输出二,以此类推。 

<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>

但是真正的执行效果是,不管点击第几个li,都会输出3。

因为 i 是贯穿整个作用域的,而不是给每个 li 分配了一个 i,用户触发的onclick事件之前,for循环已经执行结束了,而for循环执行完的时候i=3。

1. 利用立即执行函数解决

<body>
    <ul id="list">
      <li>公司简介</li>
      <li>联系我们</li>
      <li>营销网络</li>
    </ul>
</body>

<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>

改变变量i的作用域,把全局变量i以参数的形式传递到立即执行函数中,在立即执行函数中定义变量i的形参变量j,变量j就是在立即执行函数的作用域中。(给每个li创建了一个作用域块,点击的时候寻找自由变量j,在立即执行块中找到) 

2. 使用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>

3. 立即执行函数的参数

(function(j){
//代码中可以使用j
})(i)

如果立即执行函数中需要全局变量,全局变量会被作为一个参数传递给立即执行函数(上例中的i就是一个全局变量,i代表的是实参,j是i在立即执行函数中的形参)。

二. 闭包函数

1. 变量的作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

2. 如何从外部读取局部变量?

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。

3. 闭包的概念

闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

4. 闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

当看到function函数里面嵌套function函数,就是闭包。

当想访问函数内部的变量时,或想把函数内部的变量抛到外面,就需要用到闭包的写法。

父函数将子函数作为返回值,再将子函数赋值给一个变量。所以子函数会存在于内存中,而子函数依赖于父函数的存在,所以父函数也会存在于内存中。也就不会被垃圾回收机制回收。

5. 闭包的写法(用法)

在主函数function内部,定义闭包function函数。但是执行调用还是在外面的,即通过return才能调用执行。

其中,funOne是外部函数,funTwo是内部函数。funOne()的返回值是函数funTwo,funTwo在funOne()作用域内部,所以它可以获取funOne作用域下变量num的值,并将这个值作为作为返回值赋值给全局作用域下的变量fun。实现了在全局变量下获取到局部变量中的变量的值。调用外部函数funOne并将其赋值给fun时,打印fun,可以看到会返回函数funTwo。

将闭包与匿名函数结合起来,可以这样用:

注意:在我console.log(fun())的结果中,每一次都是在前一次的基础上发生了变化的(从1>2>3),这说明,num的结果每一个都被保留了下来

而在console.log(funTwo())的结果中,每一次都是一样的(都是1),这说明,里面的num每一次都被销毁重建了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值