作用域 作用域链 闭包 思想 JS/C++比较

时间:2022-12-03 15:38:25

首先,我说的比较是指JS中这种思想/实现方式与C++编译原理中思想/实现方式的比较

参考链接:(比较易懂的介绍,我主要写个人理解)

      作用域链: http://www.cnblogs.com/dolphinX/p/3280876.html

      闭包:http://kb.cnblogs.com/page/110782/

个人理解:

作用域链:

  1. 在JS中,function也是一种object的实例。
  2. 作用域的概念必须已经知晓。
  3. 作用域链:用于标识符解析:确定数据的存储位置以及数据作用域(数据访问)。(应该可以扩展)
  4. 函数执行时会创建“运行期上下文”的内部对象,当函数执行完毕后被销毁(与闭包性能有关)
  5. C++等应该不存在这类问题。因为C++函数内不能定义函数(除了lambda外),而函数调用则会在调用完后局部变量自动释放
  6. scope chain代表引用链,使用的时function对象中内置的scope属性,
  7. scope chain采用倒排索引,局部靠前,且数据访问从索引链中依次访问(性能提升点!!)
  8. 所以,局部变量会覆盖全局变量/外层变量,由此可知原因。
  9. 类比编译原理,在汇编语言中,子函数要访问外层变量,使用的。。方法也与此思想相似,
  10. 猜测:数据的存储与访问是编程语言的共同问题,而作用域链是解决这种问题的一种思想。而且,这有验证了一件事:程序逻辑和数据管理真的是编程语言的精髓!

闭包:理解作用域链之后,闭包就容易理解多了。

  1. 闭包概念:要执行的代码块(包含*变量) + 为*变量提供绑定的计算环境(作用域)。
  2. 闭包表现:function parent(){ var a; function child(){return ++a;} }
  3. 其实闭包就是调用function对象的funtion属性(只是这属性也是对象而已)的一种特殊情况
    1. 通常情况:如果 child不需要访问外层变量,则函数执行完毕后被销毁(作用域结束)
    2. 特殊情况(闭包):如果child需要访问外层变量,则外层函数执行完后,由于child函数对其存在引用,外层函数激活对象无法被销毁,导致内存开销增增加,而且外层变量的引用在scope chain中的位置也会影响数据访问的性能。
    3. 虽然闭包有各种问题,但是访问外层变量却是很有必要的操作。
    4. 参考这个函数:pushAny函数返回值是函数,即longLiveSeniorFunc是函数,而且保留了plusAny函数(外层函数)的变量senior不被释放。
       1 function plusAny(senior) {
      2 return function(second) {
      3 return senior + second;
      4 }
      5 }
      6
      7 /* usage */
      8
      9 var senior = 2838240000;
      10 var longLiveSeniorFunc = plusAny(senior);
      11
      12 longLiveSeniorFunc(1); // +1s
      13 longLiveSeniorFunc(3600); // +1h
      14 longLiveSeniorFunc(86400); // +1d
      15
      16 作者:张玳
      17 链接:https://www.zhihu.com/question/51402215/answer/125701810
      18 来源:知乎
      19 著作权归作者所有,转载请联系作者获得授权。