Rumah  >  Soal Jawab  >  teks badan

node.js - javascript作用域的问题,就是内嵌函数访问外层函数变量的问题,求大神指导我?

众所周知,在javascript中,内嵌函数,可以访问所有外层函数的变量,这个是由著名的js作用域链实现的,但是我只是从语法特性的角度去理解这个知识点的,不知道里面具体原理是什么呢?
就比如,我们在chrome中去尝试这个访问:

我们发现:height变量压根不存在,肯定为not available,但是局部变量textVar和count也是not available;color作为全局变量可以访问到,值就是red。
下面是firefox里面的测试结果:

firefox中,height变量height is not defined很好理解,但是textVar和count爆出错误variable has been optimized out是什么意思?

我们稍微修改下代码:

这次,我们特意在内嵌函数里面访问下count变量,count变量的值在Watch里面正确读取到了,但是textVar依旧没有被访问到,相对于上面那个测试,是不是很奇怪?js解释引擎到底怎么处理类似逻辑的?
下面是firefox里面的测试结果:

这个测试结果和chrome测试结果保持一致,就不累述了。

为了进一步研究,我们写nodejs测试,用webstorm对nodejs代码调试:

看了一下Watchers,发现nodejs简直丧心病狂,全局变量color都变得不可访问了。
仿照上面的套路,我们在函数里面显式访问textVar,结果是:

显式访问textVar变量,textVar在Watchers里面访问到了。


很多小伙伴认为我在讨论闭包问题,我在此申明下,我讨论的是js作用域链问题:

不是闭包吧,还是一样的测试结果!!!我讨论的是js作用域链的问题,探究的是js作用域的底层实现,虽然是个小美工,但是想跟你们多学点东西嘛。

大家讲道理大家讲道理2722 hari yang lalu581

membalas semua(15)saya akan balas

  • 黄舟

    黄舟2017-04-11 09:14:11

    @Kathy_Miao 已经说的很清楚了,把断点打在return行上就能够清楚的看到了:

    balas
    0
  • 天蓬老师

    天蓬老师2017-04-11 09:14:11

    就是闭包里返回的函数里没有你要的变量而已。
    楼主很有探索精神,值得学习,加油!

    balas
    0
  • 黄舟

    黄舟2017-04-11 09:14:11

    本来看到这个问题的,没有回答,但是别人邀请回答了,那就说两句。
    首先,你这么书写跟作用域链(不知道你说的是不是原型链)没有任何关系,你这样定义的变量是不会绑定到prototype上的。

    这个跟闭包有一定的关系,因为闭包很容易导致内存泄露(这其实不是闭包的问题),所以浏览器做了一定的优化(很多人也提到的)。

    可以参考这里:
    http://stackoverflow.com/questions/26776...
    (尤其是下面这篇)
    http://stackoverflow.com/questions/28388...

    balas
    0
  • 怪我咯

    怪我咯2017-04-11 09:14:11

    学习精神可嘉~ 其实上面都说的很多了 多看看闭包的知识 JS知识点太多 甚至多过C++

    balas
    0
  • PHPz

    PHPz2017-04-11 09:14:11

    首先谢谢题主的邀请。
    我个人非常欣赏题主这样,对知识的不断的学习研究。
    同时,也很讨厌那些瞧不起题主,嫌麻烦的人。
    不论技术问题的难度高低,任何人都可以提问题,获取自己想要的知识。回答的人,有一个展示自己的机会,知识自由的传播。

    我想,这才是segmentfault这个平台的价值。

    题主要搞明白这个问题,要明白两个知识点。
    1.变量的作用域。
    2.闭包的定义。

    1.变量的作用域
    那些说把断点打在return上的人,我都不知道说什么好了。这样打断点程序执行在外层函数,还没进內嵌函数呢。

    最内层函数可以访问在它外层的对象,直到全局对象。
    这也就解释了,题主在內嵌函数打断点,可以看到全局对象。

    2.闭包
    首先,把闭包理解成一个对象,他包含两部分--內嵌函数和他被创建时的执行环境。
    这个执行环境也就是说当时的他能访问到的对象,这些对象的状态会被保存下来。

    到这里,题主想一下,程序保存6下来当时能够访问的所有对象的状态,还是保存下来他要访问的对象的状态?

    答案肯定是保存他要访问的对象的状态。
    因为,其他对象对这个函数的执行根本没关系。出于资源,程序复杂性的考虑,根本就没有理由保存那些没有用的东西。
    这样也就解释了,题主打断点,只能看见函数里访问到的变量。

    至于,firefox和chrome提示的内容不一样。这就是不同浏览器厂商各自实现的问题了,但可以肯定,他们做的事情是一样的,只是实现细节上不太一样。而且,我认为FIREFOX的更准确一些。

    balas
    0
  • Batalbalas