• javascript 闭包的理解(二)


        // 定义一个User构造函数
        function User(properties){
            //遍历对象属性,确保它作用域正确
            for(var i in properties){
                (function(which){
                    var p = i;
                    //为属性创建获取器
                    which["get"+i] = function(){
                        return properties[p];    
                    };
                    //为属性创建设置器
                    which["set"+i] = function(val){
                        properties[p] = val;    
                        //return properties[p];
                    };
                })(this);
            }
        }
        
        // 创建一个User实例
        var user = new User({
            name:"Bob",
            age:44,
            islive:true,
            money:50000,
            earn:5000,
            nation:"china",
            job:"web Dev"    
        });
    
    
            user.getname();           // 返回 "Bob"
            user.getage();              // 返回 "44"
    
            user.getage.call(window);      // 依然返回44
            user.getage.call({age: 23});  // 还是返回44

    上面的这段代码(我们叫它代码段A吧)里, user.getage.call(window)user.getage.call({age: 23}) 返回的结果,虽然在意料之中,但是我却并不非常清楚的知道为什么是这样。

    我只是大概的知道,之所以是这个结果,肯定跟User构造函数里的闭包有关系。

    我认为User构造函数里有两个闭包,所以我猜想调用user.getage的时候,就生成了2个闭包作用域。

    但这只是我的猜想,事实是不是这样的呢?我想到了一个办法来验证:使用console.dir()

    var getage = user.getage;
    
    console.dir(getage);

    输出如下:

    从输出的对象结构,可以看到这个方法它的[[Scopes]]确实有两个Closure,而且每个Closure里面有些什么东西也显示出来了。

    我猜想在执行getage方法时,会先执行第一个闭包作用域,也就是Closure 0,这个闭包是由代码段A里的以下代码生成的:

    which["get"+i] = function(){
        return properties[p];    
    };

    我觉得这里应该搞清楚闭包、闭包作用域、闭包包含的作用域 三个概念,否则理解起来会很蒙,搞不清楚。

    闭包:就是以上代码所定义的函数which[“get”+i]。

    闭包作用域:就是由以上代码生成的执行上下文空间,它就是对象结构图中的那个[[Scopes]]。

    闭包包含的作用域:可以看到[[Scopes]]里面还包含了getage闭包引用的另外两个闭包的作用域里的变量:立即执行函数的作用域里的变量p 和 User函数作用域里的变量i变量properties

    从对象结构里可以看到,闭包 Closure 0 里面存在一个变量p,因此执行闭包时,会去闭包作用域里搜索p,但搜索不到,因为p是在立即执行函数的作用域里定义的,所以会立即进入搜索Closure 0作用域的流程。

    搜索Closure 0时,找到了p,并且发现p = i,此时p的定义找到了,但p等于i,所以进入搜索变量i的定义的流程。

    因为变量i没有在立即执行函数里定义,所以Closure(User)被保留了下来,在立即执行函数的作用域里找不到变量i,就进入Closure(User)作用域寻找,找到了i,同时应为是立即执行函数,所以i的值一搜索到,就理解返回给p,并存入Closure 0作用域中,而Closure(User)中的i的值由于程序继续执行而变化,最后只会存入最后设置给i的值。

    properties的值也是一样,在闭包作用域里找不到,就会去立即执行函数的作用域里找,找不到再去Closure(User)里找,找到了立即返回。

    所以上面那段生成闭包 Closure 0 的代码执行后,返回的结果就是 properties[i],此时闭包作用域使用完毕,不再需要,可以回收,进入解析Closure(User)作用域的步骤

    然后properties[i] 被解析为 properties[“age”],然后被返回。

  • 相关阅读:
    pycharm中文乱码
    bootstrap-table分页
    sql将查询结果的某个字段赋值给另一个字段
    bootstrap tab选项卡
    cocos-js 精灵移动转圈
    配置环境变量路径有空格
    配置java环境遇到的问题及解决方案
    obj = obj || {} 分析这个代码的起到的作用
    sql server行转列
    sql server统计总成绩和排名
  • 原文地址:https://www.cnblogs.com/macliu/p/11161414.html
Copyright © 2020-2023  润新知