变量,作用域链,指向函数与执行函数,闭包

作者: 吴立宁 | 来源:发表于2016-03-17 23:19 被阅读113次

    在学习写轮播图,还有学习《js高级程序设计》中的执行环境,变量,作用域,函数,闭包时所想所感
    下面我主要写的是变量的指向,变量指向的函数,变量指向的函数的执行,变量指向的函数执行时的作用域
    先写一个超级简单的

    function fn() {
        var result = 1;
        console.log(result);
        return result;
    }
    var result1 = fn;
    var result2 = fn();
    console.log(result1,result2);
    //结果
    1
    function fn() {
          var result = 1;
          console.log(result);
          return result;
    } 1
    

    超级简单是吧,但是要明白这中间的过程是什么,一步步来:

    1. 定义了一个变量fn和一个函数,函数的内容是var result = 1; ...,将变量fn指向这个函数

    算了还是稍微画个图吧
    对于栈和堆还不是很了解

    测试图片
    为了等下更好理解函数,这里的所有变量的值都当做引用类型,所有的变量都是指向,给变量加上()相当与执行变量所指向的函数
    还是简单一点的
    function fn() {
        var result = [];
        for (var i=0;i<3;i++) {
            result[i] = function() {
                return i;
            }
        }
        return result;
    }
    var result1 = fn();
    var result2 = result1[0]();
    var result3 = result1[1]();
    var result4 = result1[2]();
    console.log(result1,result2,result3,result4);
    // 结果
    [function...,function...,function...] 3 3 3
    
    1. 将fn指向function(){var result = []...}
    2. 执行fn所指向的function,新建result,将result指向一个Array,将result[0]指向function(){return i;},result[1]指向另一个function(){return i;},result[2]也一样,虽然内容一样,不过这是不同的三个函数,返回result,这时result1指向result
    3. 执行result[0]所指向的函数,返回i,但是arguments没有,自己本身没有定义,所以根据作用域链,只能在上级函数中找到,这时候函数中的语句已经在第二步执行完毕,i=3,所以返回了3,result2就指向3,这下重点来了,这里就算是闭包的部分了,通常来说,当fn所指向的函数执行完毕后会销毁其活动对象,也就是定义的result,i等等,但是因为返回的result的词法作用域(lexcical scope)是在定义时确定的,(先不管with和trycatch),要用到i,这时就保留了上级函数的活动对象,以便于result所指向的函数访问,后面的两个相同
    4. 打印出他们指向的值

    再看一个

    function fn() {
        var result = [];
        for (var i=0;i<3;i++) {
            result[i] = (function() {
                return i;
            })();
        }
        return result;
    }
    var result1 = fn();
    var result2 = result1[0];
    var result3 = result1[1];
    var result4 = result1[2];
    console.log(result1,result2,result3,result4)
    // 结果
    [0, 1, 2] 0 1 2
    

    这次在result所指向的的函数后面加上了(),在result2,3,4后面取消了()

    1. 执行fn指向的函数,和上一次相同,定义函数,但是立即执行,这时result[0]就指向这个函数的的返回值,第一此循环i=1,执行一次function(){return i;},同样向上找到i=1,返回1,result[0]就指向1,后面的相同,然后返回result
    2. 这时候fn()就指向了在堆中的那个Array,result也就指向那个Array
    3. 打印

    这下稍微难点的

    function fn() {
        var result = [];
        for (var i=0;i<3;i++) {
            result[i] = (function(i) {
                return function() {
                    return i;
                };
            })(i);
        }
        return result;
    }
    var result1 = fn();
    var result2 = result1[0]();
    var result3 = result1[1]();
    var result4 = result1[2]();
    console.log(result1,result2,result3,result4)
    // 结果
    [function...,function...,function...] 0 1 2
    
    1. 执行fn指向的函数,和上一次相同,定义函数,立即执行,这时result[0]指向函数function(){return i};
      ,result[1]指向另一个function(){return i;},result[2]同上,返回result,是不是感觉和第一次一样,但是等下判断i的值就不一样了
    2. 执行result1[0]指向的函数function(){return i;},先在自己的作用域中找,没有,向上找,就是那个立即执行的函数中找,arguments中有,这时的i是3吗?显然不是的,是立即执行时传入的i,因为返回的function(){return i;}在定义时传入的0,所以这时的i为0,还记得刚才写的,词法作用域(lexcical scope)是在定义时确定的,return fuction(){}也可以理解为var anonymous = function(){}; return anonymous;同理后面返回1和2
    3. 打印

    相关文章

      网友评论

        本文标题:变量,作用域链,指向函数与执行函数,闭包

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