• 常让人误解的一道js小题


     一道小题引发的深思    

         今天无意中看到一个js笔试题,不由得想起初学js那会被各种题目狂虐的心酸,虽说现在也会被笔试题所虐,但毕竟比之前好了很多,下面就是我的个人理解,欢迎拍砖、指正:

    var x = 1;
    function printx(){
        console.log(x);
        
    }
    
    function show(f){
        var x = 2;
        (function(){
            f();
        })()
    }
    
    show(printx); //1 

         结果后台会打印1,而不是2。这有些不合常理,因为很多人会错误的认为:函数show中的f()在执行时,由于本作用域中没有x,所以会向上层作用域寻找x,当找到上层函数show的作用域中时发现 var x=2,这时就把x确定为2,否则会继续向上找,直至window。。。终于用到所谓的“作用域链”啦!大喜,其实这样想你就错了!

       第一:首先有这么一个名词叫“自由变量”,自由变量是指:如果作用域(函数)A中使用到了变量x,而x并不是在作用域(函数)A中定义,那么对于作用域(函数)A来说,x就是A的自由变量。

       第二:理解这么一句话:js没有块级作用域,仅有的块级作用域是用函数来实现的,也就是说只有函数能创建出一块独立的作用域。if、for代码块都不行!所以本文中一个作用域可以理解为一个函数。

       第三:函数的作用域在函数定义时就已经确定,而不是在执行时确定。

        对于嵌套函数来说按照上述:寻找自由变量是沿作用域链向上一层层查找,这样理解是对的。但是这样理解太片面,甚至会产生错误,就比如上面这道题。正确的理解应该是:寻找自由变量时会到创建这个函数(作用域)的那个作用域中寻找。而创建这个函数的作用域并不一定是它位置上的父级作用域,(并不是在代码结构上包含,就是子父关系)上面这道题就是这种情况:函数show中把printx函数作为参数传入执行,在执行时会寻找创建它的那个作用域,很明显创建printx函数的作用域并不是show,而是全局window(因为printx函数在window中创建),所以它会寻找全局window中的x,此x为1。 所以会打印1,这才是正解。

          不知道我解释的清不清楚,总之:函数使用自由变量时,会到创建这个函数的那个作用域中寻找。“向父级作用域中寻找”可能会存在偏差。(不足之处欢迎指正!)

     再补充两道,加深理解

         本文的评论里还有两道更加通俗易懂的两道题,征得热心博友theWalker的同意,把他给出的两个demo也展示给大家,希望对你有所帮助:

    function a(){
      console.log(b)
    }
    function c(){
      var b = 1;
      a()
    }
    c() //b is not defined
    
     /****************************************/
    
    var b = 2;
    function a(){
      console.log(b)
    }
    function c(){
      var b = 1;
      a()
    }
    c() // 2
  • 相关阅读:
    sql,linq基础再一次学习
    position与aop
    java基础常用类!
    JNI初步!
    java基础动态代理!
    java基础面向对象!
    php初步!
    java基础泛型!
    java基础对象多态性!
    java基础io流!
  • 原文地址:https://www.cnblogs.com/chayangge/p/4342984.html
Copyright © 2020-2023  润新知