对js作用域,闭包,立即执行函数的理解

关于js中作用域,闭包,立即执行函数的理解
  1. 执行环境:
    JS中非常重要的概念,全局执行环境被认为是window对象,另外,每一个函数都有自己的执行环境。当代码在环境中执行时,会创建一个作用域链。
  2. 作用域链:
    限制变量或者函数的访问权限。
    作用域的顺序为“由内而外”,也就是说,作用域的顶端是当前执行代码所在环境的变量对象。下一个变量对象来自外一层包含环境,window对象始终都是作用域链的最后一个对象。
    因此在变量查询时,也是先从作用域链的顶端开始,找到则停止,找不到则继续向下进行。
    作用域链的用途是:保证对执行环境有权访问的所有变量和函数的有序访问。
    在这里小提一下,如果定义变量的时候没有使用关键字,则会生成一个全局变量
    一个非常简单的例子:
<script>
    var a =10;
    function fun()
    {
        var a=3;
        alert(a);//3
    }
    fun();
    alert(a);//10
</script>

对于JS来说,不存在块级作用域(所谓块级作用域就是用大括号包起来的部分,比如说if,while,for中)。看一个简单的例子。

<script>
    var a = 10; 
    if(a==10)
    {
        var a=8;
    }
    alert(a);//8
</script>

而对于C家族语言来说,是存在块级作用域的

#include<stdio.h>
int main()
{
    if(1)
    {
        int a=1;
    }
    printf("%d",a);//出现错误
}

接下来了解一下闭包:

  • 什么是闭包:
    1. 有权访问另一个函数作用域内变量的函数
    2. 创建时通常需要用到函数的嵌套
    3. 会“阻碍”js的垃圾销毁机制,因为内部的函数会用到外部函数的变量,所以不能销毁外部函数的执行环境,因此经常会说到闭包会增大内存的开销。
    4. 跨作用域访问
    5. 大概扯到这里会有些迷,辣就来个栗子吧
function func1(){
    var name="zhangsan";
    function func2(){
        return name;
    }
    return func2();
}
var thatname=func1();
console.log(thatname);//zhangsan

通常情况下,我们是不能再函数外部获取函数内的变量的,子作用域可以访问父作用域中的变量,反之不行。此时就需要用到闭包,即可以实现跨作用域的访问,外部可以访问内部啦。
再看一个栗子:

     function create(){
        var result=new Array();
         for(var i=0;i<10;i++){
             result[i]=function(){
                 console.log(i);
             };
         }
         return result;
     }
     var createresult=create();
     createresult[5]();//10

这里返回了一个函数数组,看起来每个函数应该打印自己的索引值,但是实际上每个函数打印的都是10,这是因为i这个变量在for循环结束后变成了10,并且在for循环结束后仍然有效。
解决方法是创建一个立即执行函数。

function create(){
   var result=new Array();
    for(var i=0;i<10;i++){
        result[i]=(function(num){
            console.log(num);
        })(i);
    }
    return result;
}
var createresult=create();//输出0-9

这里i的值传给了num,立即执行函数我的理解就是立即执行这个函数,当然也有其他的解决办法,如ES6中的let.

  • 下面说一些值得注意的地方
    1. 使用完闭包,建议手动销毁,以释放内存。对于如上代码片,可以用thatname=null销毁
    2. javascript函数运行在定义它的作用域中,而不是执行时的作用域中。比如说下面的例子:
var name="zhangsan";
function func1(){
    console.log(name);
}
function func2(){
    var name="lisi";
    func1();
}
func2();//zhansan

func2中去掉var是不一样的,相当于修改了全局的name的值

var name="zhangsan";
function func1(){
    console.log(name);
}
function func2(){
    name="lisi";
    func1();
}
func2();//lisi

先这些吧,有新的想法再和大家分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值