博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS 作用域(执行环境)与作用链---JS 学习笔记(二)
阅读量:5840 次
发布时间:2019-06-18

本文共 2544 字,大约阅读时间需要 8 分钟。

一  作用域(执行环境)

作用域:定义了变量和函数有权访问的其他数据,决定了他们各自的行为。--------《JS高级程序设计》4.2 

好难理解啊~参考了参考的博客内容,大体上理解了作用域。 

作用域规定了函数和变量的可用的有效的范围。这样的好处是,避免了命名冲突;确定何时销毁他们,释放内存。这个作用域中所有的函数和对象,都保存在变量对象里。每个作用域都有这样一个变量对象。但是我们编写的代码是无法访问到这个对象的,解析器在处理数据时会在后台使用它。

作用域分为两类:全局作用域和函数作用域。

全局作用域是最外围的一个作用域。根据 ECMAScript 实现所在的宿主环境不同,表示作用域的对象也不一样。在 Web 浏览器中,全局作用域是 Window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的。当某一个作用域中所有的代码都执行完以后,作用域被销毁, 作用域里面的变量和函数,也随之销毁。(全局执行环境直到应用程序退出----例如关闭网页或者浏览器------这时才被销毁)  ----------- 《JS高级程序设计》4.2

环境栈:每个函数都有自己的作用域,当执行流进入一个函数时,函数的作用域就会被推入一个环境栈中。函数执行完毕后,这个函数的作用域被环境栈弹出,把控制权交还给之前的作用域。

在一个页面中,第一次载入JS代码时创建一个全局执行环境,当调用一个 JavaScript 函数时,该函数就会进入相应的执行环境。如果又调用了另外一个函数(或者递归地调用同一个函数),则又会创建一个新的执行环境,并且在函数调用期间执行过程都处于该环境中。当调用的函数返回后,执行过程会返回原始执行环境。因而,运行中的 JavaScript 代码就构成了一个执行环境栈。(参考)。

举个例子,下面程序的环境栈如下图:

var cloth = 'shirt';function f1() {    var anotherCloth = 'pants';        function f2() {        var drink = 'juice';    }   f2();} f1();

 

 

 

二  作用域链

当代码在一个作用域中执行时,会创造一个作用域链(scope chain)。作用域链的用途是,保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端始终都是当前执行的代码所在环境的变量对象。作用域链的下一个变量对象,来自包含(外部)环境,而在下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境;全局执行环境始终都是作用域链的最后一个对象。

标识符解析是沿着作用域链一级级搜索标识符的过程。搜索过程始终都是从作用域链的前段开始,然后逐级的向后回溯,直到找到标识符为止(如果找不到标识符,通常会导致错误发生。)

-----《JS高级程序设计》4.2

举例来理解:

1 var color = 'blue'; 2  3 function changeColor() { 4     var anotherColor = "red" 5      6     function swapColors() { 7         var tempColor = anotherColor; 8         anotherColor = color; 9         color = tempColor;10     11     // 这里可以访问 color、anotherColor 和 tempColor12     }13     14     // 这里可以访问 color 和 anotherColor。不能访问 tempColor15     16     swapColors()17 }18   19 // 这里只能访问 color20 21 changeColor()22

 

上面代码在执行的时候有三个作用域:全局作用域、changeColor() 作用域和 swapColors() 作用域。他们的作用域链如下图:

 

 

作用域链的本质是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。

 

三  块级作用域

块级作用域,就是在 for、if  等里面定义的变量,在 for、if 执行完毕以后,这些变量也会被销毁。ES6 之前的版本,是没有块级作用域的。ES6 新增加了 let 和 const 关键字,就有了块级作用域。例如下面的代码:

 

1 if (true) {2     var color = 'blue';3 }4   5 alert(color);  // 'blue'       color 变量在 if 语句执行完以后并没有被销毁if 语句执行完以后,还会在外面访问到 if 里面的 color变量。
1 if (true) {2     let color = 'blue'; 3 } 4 5 alert(color); // color is not defined color 变量在 if 语句执行完毕以后,被销毁,外部访问不到 if 语句块里面定义的 color 变量。

 

1 for (var i=0; i < 10; i++) { 2     var a = 1; 3 } 4  5 alert(i) // 10     6  7 for (const i=0; i < 10; i++) { 8     var a = 1; 9 }10 11 alert(i) // invalid assignment to const `i'

未解决的问题:

if 语句用 const 实现不了块级作用域,for 语句用 let 实现不了会计作用域。这个疑惑还要后续再查找资料补充。

补充结果:let 用在块作用域定义变量,而 const 在块作用域定义常量。即在块作用域中,一旦使用 const a = 1;那么,在块作用域中,就不能再给 a 赋值别的值了。因为,此时 a 已经是一个常量了。

 

转载于:https://www.cnblogs.com/rougan/p/10563250.html

你可能感兴趣的文章
log4j2的使用总结
查看>>
基于swift4.0实现视频播放、屏幕旋转、倍速播放、手势调节,锁屏面板等功能
查看>>
数据库的设计原则
查看>>
Java多线程学习(1)创建线程与线程的生命周期
查看>>
QUdp不能很好支持大网络数据包情况
查看>>
React DOM Diff算法详解
查看>>
你真的理解 flex 布局吗?
查看>>
三数之和[LeetCode-15]
查看>>
聊一聊Swift拓展
查看>>
JavaScript时间格式与字符串格式转换
查看>>
js return;后返回为空页面
查看>>
工作五年难道必须要读源码吗?
查看>>
如果让你写一个消息队列,该如何进行架构设计啊?
查看>>
浅谈移动端适配大法
查看>>
Android精通:TableLayout布局,GridLayout网格布局,FrameLayout帧布局,AbsoluteLayout绝对布局,Relativ...
查看>>
Java面试集合(四)
查看>>
G IP地址转换
查看>>
新的iOS开发方式,无需服务器,做自己的前端转原生iOS app的框架
查看>>
[译] 网络现状:性能提升指南
查看>>
python主机批量管理脚本(上)
查看>>